From a07daa8f98d42394c00520e680d0db54dadbc9c0 Mon Sep 17 00:00:00 2001 From: Gianluca Date: Fri, 18 Sep 2020 18:45:14 +0200 Subject: [PATCH] documentation, refactoring and lot of stuff --- .gitmodules | 3 + README.md | 40 +- cmd/driplane/main.go | 10 + config.yaml.example | 7 +- core/configuration.go | 5 + core/orchestrator.go | 6 + core/pipe_rule.go | 18 +- core/rule_parser.go | 12 +- core/version.go | 3 +- data/message.go | 13 +- docs/archetypes/default.md | 6 + docs/config/_default/config.toml | 41 + docs/config/_default/languages.toml | 4 + docs/config/_default/menus.en.toml | 5 + docs/config/_default/params.toml | 24 + docs/content/_index.md | 124 +-- docs/content/doc/_index.md | 48 ++ docs/content/doc/configuration/_index.md | 44 + docs/content/doc/feeders/_index.md | 17 + docs/content/doc/feeders/file.md | 39 + docs/content/doc/feeders/rss.md | 54 ++ docs/content/doc/feeders/twitter.md | 63 ++ docs/content/doc/feeders/web.md | 55 ++ docs/content/doc/filters/_index.md | 7 + docs/content/doc/filters/cache.md | 35 + docs/content/doc/filters/changed.md | 30 + docs/content/doc/filters/echo.md | 30 + docs/content/doc/filters/format.md | 36 + docs/content/doc/filters/hash.md | 48 ++ docs/content/doc/filters/http.md | 43 + docs/content/doc/filters/js/_index.md | 8 + docs/content/doc/filters/js/basics.md | 32 + docs/content/doc/filters/js/entrypoint.md | 52 ++ docs/content/doc/filters/js/packages.md | 120 +++ docs/content/doc/filters/mail.md | 46 + docs/content/doc/filters/override.md | 32 + docs/content/doc/filters/system.md | 32 + docs/content/doc/filters/text.md | 42 + docs/content/doc/filters/url.md | 45 + docs/content/doc/installation/_index.md | 8 + docs/content/doc/installation/build.md | 14 + docs/content/doc/installation/docker.md | 12 + docs/content/doc/rules/_index.md | 7 + docs/content/doc/rules/definition.md | 20 + docs/content/doc/rules/syntax.md | 76 ++ docs/go.sum | 10 + ...s_b4f67ac5085b89b62b54c1923e5a9145.content | 1 + ...scss_b4f67ac5085b89b62b54c1923e5a9145.json | 1 + ...s_c14439616ffbc3ae1827507340d6c08b.content | 490 +++++++++++ ...scss_c14439616ffbc3ae1827507340d6c08b.json | 1 + ...s_d18af36970f1f09b308ef20ee65e3a03.content | 803 ++++++++++++++++++ ...scss_d18af36970f1f09b308ef20ee65e3a03.json | 1 + ...s_c14439616ffbc3ae1827507340d6c08b.content | 490 +++++++++++ ...scss_c14439616ffbc3ae1827507340d6c08b.json | 1 + ...s_d18af36970f1f09b308ef20ee65e3a03.content | 803 ++++++++++++++++++ ...scss_d18af36970f1f09b308ef20ee65e3a03.json | 1 + docs/static/favicon/android-icon-144x144.png | Bin 0 -> 8518 bytes docs/static/favicon/android-icon-192x192.png | Bin 0 -> 12361 bytes docs/static/favicon/android-icon-36x36.png | Bin 0 -> 2068 bytes docs/static/favicon/android-icon-48x48.png | Bin 0 -> 2699 bytes docs/static/favicon/android-icon-72x72.png | Bin 0 -> 3951 bytes docs/static/favicon/android-icon-96x96.png | Bin 0 -> 5273 bytes docs/static/favicon/apple-icon-114x114.png | Bin 0 -> 6274 bytes docs/static/favicon/apple-icon-120x120.png | Bin 0 -> 6607 bytes docs/static/favicon/apple-icon-144x144.png | Bin 0 -> 8518 bytes docs/static/favicon/apple-icon-152x152.png | Bin 0 -> 9320 bytes docs/static/favicon/apple-icon-180x180.png | Bin 0 -> 12131 bytes docs/static/favicon/apple-icon-57x57.png | Bin 0 -> 3152 bytes docs/static/favicon/apple-icon-60x60.png | Bin 0 -> 3272 bytes docs/static/favicon/apple-icon-72x72.png | Bin 0 -> 3951 bytes docs/static/favicon/apple-icon-76x76.png | Bin 0 -> 4121 bytes .../static/favicon/apple-icon-precomposed.png | Bin 0 -> 12850 bytes docs/static/favicon/apple-icon.png | Bin 0 -> 12850 bytes docs/static/favicon/browserconfig.xml | 2 + docs/static/favicon/favicon-16x16.png | Bin 0 -> 1195 bytes docs/static/favicon/favicon-32x32.png | Bin 0 -> 1925 bytes docs/static/favicon/favicon-96x96.png | Bin 0 -> 5273 bytes docs/static/favicon/favicon.ico | Bin 0 -> 1150 bytes docs/static/favicon/logo.png | Bin 0 -> 25687 bytes docs/static/favicon/logo192x192.png | Bin 0 -> 7716 bytes docs/static/favicon/manifest.json | 41 + docs/static/favicon/ms-icon-144x144.png | Bin 0 -> 8518 bytes docs/static/favicon/ms-icon-150x150.png | Bin 0 -> 9160 bytes docs/static/favicon/ms-icon-310x310.png | Bin 0 -> 28146 bytes docs/static/favicon/ms-icon-70x70.png | Bin 0 -> 3766 bytes docs/static/logo.png | Bin 0 -> 7716 bytes docs/themes/zdoc | 1 + feeders/base.go | 17 +- feeders/file.go | 8 +- feeders/rss.go | 10 +- feeders/twitter.go | 13 +- feeders/web.go | 16 +- filters/base.go | 17 +- filters/cache.go | 3 + filters/changed.go | 4 + filters/echo.go | 3 + filters/format.go | 11 +- filters/hash.go | 3 + filters/http.go | 25 +- filters/js.go | 15 +- filters/mail.go | 12 +- filters/override.go | 5 + filters/system.go | 12 +- filters/text.go | 3 + filters/url.go | 55 +- filters/utils/global_ttl_map.go | 2 + filters/utils/ttl_map.go | 7 +- go.sum | 1 + plugins/file.go | 75 +- plugins/http.go | 66 +- plugins/log.go | 5 + plugins/strings.go | 16 +- plugins/util.go | 28 +- utils/cookie.go | 2 + utils/html.go | 7 +- utils/misc.go | 3 + 116 files changed, 4224 insertions(+), 282 deletions(-) create mode 100644 .gitmodules create mode 100644 docs/archetypes/default.md create mode 100644 docs/config/_default/config.toml create mode 100644 docs/config/_default/languages.toml create mode 100644 docs/config/_default/menus.en.toml create mode 100644 docs/config/_default/params.toml create mode 100644 docs/content/doc/_index.md create mode 100644 docs/content/doc/configuration/_index.md create mode 100644 docs/content/doc/feeders/_index.md create mode 100644 docs/content/doc/feeders/file.md create mode 100644 docs/content/doc/feeders/rss.md create mode 100644 docs/content/doc/feeders/twitter.md create mode 100644 docs/content/doc/feeders/web.md create mode 100644 docs/content/doc/filters/_index.md create mode 100644 docs/content/doc/filters/cache.md create mode 100644 docs/content/doc/filters/changed.md create mode 100644 docs/content/doc/filters/echo.md create mode 100644 docs/content/doc/filters/format.md create mode 100644 docs/content/doc/filters/hash.md create mode 100644 docs/content/doc/filters/http.md create mode 100644 docs/content/doc/filters/js/_index.md create mode 100644 docs/content/doc/filters/js/basics.md create mode 100644 docs/content/doc/filters/js/entrypoint.md create mode 100644 docs/content/doc/filters/js/packages.md create mode 100644 docs/content/doc/filters/mail.md create mode 100644 docs/content/doc/filters/override.md create mode 100644 docs/content/doc/filters/system.md create mode 100644 docs/content/doc/filters/text.md create mode 100644 docs/content/doc/filters/url.md create mode 100644 docs/content/doc/installation/_index.md create mode 100644 docs/content/doc/installation/build.md create mode 100644 docs/content/doc/installation/docker.md create mode 100644 docs/content/doc/rules/_index.md create mode 100644 docs/content/doc/rules/definition.md create mode 100644 docs/content/doc/rules/syntax.md create mode 100644 docs/go.sum create mode 100644 docs/resources/_gen/assets/scss/driplane/sass/main.scss_b4f67ac5085b89b62b54c1923e5a9145.content create mode 100644 docs/resources/_gen/assets/scss/driplane/sass/main.scss_b4f67ac5085b89b62b54c1923e5a9145.json create mode 100644 docs/resources/_gen/assets/scss/driplane/scss/slate/print.css.scss_c14439616ffbc3ae1827507340d6c08b.content create mode 100644 docs/resources/_gen/assets/scss/driplane/scss/slate/print.css.scss_c14439616ffbc3ae1827507340d6c08b.json create mode 100644 docs/resources/_gen/assets/scss/driplane/scss/slate/screen.css.scss_d18af36970f1f09b308ef20ee65e3a03.content create mode 100644 docs/resources/_gen/assets/scss/driplane/scss/slate/screen.css.scss_d18af36970f1f09b308ef20ee65e3a03.json create mode 100644 docs/resources/_gen/assets/scss/scss/slate/print.css.scss_c14439616ffbc3ae1827507340d6c08b.content create mode 100644 docs/resources/_gen/assets/scss/scss/slate/print.css.scss_c14439616ffbc3ae1827507340d6c08b.json create mode 100644 docs/resources/_gen/assets/scss/scss/slate/screen.css.scss_d18af36970f1f09b308ef20ee65e3a03.content create mode 100644 docs/resources/_gen/assets/scss/scss/slate/screen.css.scss_d18af36970f1f09b308ef20ee65e3a03.json create mode 100644 docs/static/favicon/android-icon-144x144.png create mode 100644 docs/static/favicon/android-icon-192x192.png create mode 100644 docs/static/favicon/android-icon-36x36.png create mode 100644 docs/static/favicon/android-icon-48x48.png create mode 100644 docs/static/favicon/android-icon-72x72.png create mode 100644 docs/static/favicon/android-icon-96x96.png create mode 100644 docs/static/favicon/apple-icon-114x114.png create mode 100644 docs/static/favicon/apple-icon-120x120.png create mode 100644 docs/static/favicon/apple-icon-144x144.png create mode 100644 docs/static/favicon/apple-icon-152x152.png create mode 100644 docs/static/favicon/apple-icon-180x180.png create mode 100644 docs/static/favicon/apple-icon-57x57.png create mode 100644 docs/static/favicon/apple-icon-60x60.png create mode 100644 docs/static/favicon/apple-icon-72x72.png create mode 100644 docs/static/favicon/apple-icon-76x76.png create mode 100644 docs/static/favicon/apple-icon-precomposed.png create mode 100644 docs/static/favicon/apple-icon.png create mode 100644 docs/static/favicon/browserconfig.xml create mode 100644 docs/static/favicon/favicon-16x16.png create mode 100644 docs/static/favicon/favicon-32x32.png create mode 100644 docs/static/favicon/favicon-96x96.png create mode 100644 docs/static/favicon/favicon.ico create mode 100644 docs/static/favicon/logo.png create mode 100644 docs/static/favicon/logo192x192.png create mode 100644 docs/static/favicon/manifest.json create mode 100644 docs/static/favicon/ms-icon-144x144.png create mode 100644 docs/static/favicon/ms-icon-150x150.png create mode 100644 docs/static/favicon/ms-icon-310x310.png create mode 100644 docs/static/favicon/ms-icon-70x70.png create mode 100644 docs/static/logo.png create mode 160000 docs/themes/zdoc diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..9dc9f6b --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "docs/themes/zdoc"] + path = docs/themes/zdoc + url = https://github.com/zzossig/hugo-theme-zdoc.git diff --git a/README.md b/README.md index 6142220..d48580d 100644 --- a/README.md +++ b/README.md @@ -1 +1,39 @@ -# DripLane \ No newline at end of file +# Introduction + +Driplane allows you to create an automatic alerting system or start automated tasks triggered by events. +You can keep under control a source as Twitter, a file, a RSS feed or a website. +It includes a mini language to define the filtering pipelines (the rules) and contains a JS plugin system. + +With driplane you can create several rules starting from one or more streams, filter the content in the pipeline and launch task or send e-mail if some events occurred. + +The documentation can be found [HERE](https://matrix86.github.io/driplane/) + +## How it works + +The user can define one or more rules. Each rules contain a source (`feeder`), who cares of get the information and send updates (`Message`) through the pipeline, and several `filters`. +The task of the filters is to propagate or stop the `Message` to the next filter in the pipeline, or change the `Message` received before to propagate it. If the condition is verified, the `Message` will be propagated. + +## Use cases + +Using driplane is it possible to: + + * keep track of keywords or users on Twitter, receive the new tweets or quoted tweet from them, search for URLs or particular strings and send it to a Telegram or Slack channel through a webhook. + * keep track of a RSS feed or a website, and download and store on file all the new changes to them. + +The rules and the JS plugins allows you to create more complex custom logics. + +## Usage + +``` +Usage of driplane: + -config string + Set configuration file. + -debug + Enable debug logs. + -help + This help. + -js string + Path of the js plugins. + -rules string + Path of the rules' directory. +``` \ No newline at end of file diff --git a/cmd/driplane/main.go b/cmd/driplane/main.go index 1c44165..01a874a 100644 --- a/cmd/driplane/main.go +++ b/cmd/driplane/main.go @@ -2,9 +2,12 @@ package main import ( "flag" + "fmt" "github.com/Matrix86/driplane/utils" + "github.com/evilsocket/islazy/tui" "os" "os/signal" + "runtime" "syscall" "github.com/Matrix86/driplane/core" @@ -21,6 +24,7 @@ var ( configFile string ) +// Signal stops feeders on SIGINT or SIGTERM signal interception func Signal(o *core.Orchestrator) { sChan := make(chan os.Signal, 1) @@ -45,6 +49,12 @@ func main() { flag.BoolVar(&debugFlag, "debug", false, "Enable debug logs.") flag.Parse() + appName := fmt.Sprintf("%s v%s", core.Name, core.Version) + appBuild := fmt.Sprintf("(built for %s %s with %s)", runtime.GOOS, runtime.GOARCH, runtime.Version()) + appAuthor := fmt.Sprintf("Author: %s", core.Author) + + fmt.Printf("%s %s\n%s\n", tui.Bold(appName), tui.Dim(appBuild), tui.Dim(appAuthor)) + if helpFlag { flag.Usage() return diff --git a/config.yaml.example b/config.yaml.example index 8ba8db6..08a7287 100644 --- a/config.yaml.example +++ b/config.yaml.example @@ -1,8 +1,9 @@ general: - rules_path: "" - js_path: "" # if empty rules_path is used as base log_path: "" - debug: true + rules_path: "rules" + js_path: "js" + templates_path: "templates" + debug: false twitter: consumerKey: "", diff --git a/core/configuration.go b/core/configuration.go index a3eccdf..5237948 100644 --- a/core/configuration.go +++ b/core/configuration.go @@ -10,6 +10,7 @@ import ( "gopkg.in/yaml.v2" ) +// Configuration contains all the configs read by yaml file type Configuration struct { sync.RWMutex @@ -17,6 +18,7 @@ type Configuration struct { flat map[string]string } +// LoadConfiguration create a Configuration struct from a filename func LoadConfiguration(path string) (*Configuration, error) { configuration := &Configuration{ FilePath: path, @@ -66,6 +68,7 @@ func (c *Configuration) flatMap(m map[interface{}]interface{}) map[string]string return flatten } +// Get returns the config value with that name, if it exists func (c *Configuration) Get(name string) string { c.RLock() defer c.RUnlock() @@ -76,6 +79,7 @@ func (c *Configuration) Get(name string) string { return c.flat[name] } +// Set insert a new config in the Configuration struct func (c *Configuration) Set(name string, value string) error { c.Lock() defer c.Unlock() @@ -84,6 +88,7 @@ func (c *Configuration) Set(name string, value string) error { return nil } +// GetConfig returns the complete configuration in a flatten way func (c *Configuration) GetConfig() map[string]string { c.RLock() defer c.RUnlock() diff --git a/core/orchestrator.go b/core/orchestrator.go index cecbf5f..c5a6504 100644 --- a/core/orchestrator.go +++ b/core/orchestrator.go @@ -7,6 +7,7 @@ import ( "sync" ) +// Orchestrator handles the pipelines and rules type Orchestrator struct { asts map[string]*AST config *Configuration @@ -15,6 +16,7 @@ type Orchestrator struct { sync.Mutex } +// NewOrchestrator create a new instance of the Orchestrator func NewOrchestrator(asts map[string]*AST, config *Configuration) (Orchestrator, error) { o := Orchestrator{} @@ -35,6 +37,7 @@ func NewOrchestrator(asts map[string]*AST, config *Configuration) (Orchestrator, return o, nil } +// StartFeeders opens the gates func (o *Orchestrator) StartFeeders() { o.Lock() defer o.Unlock() @@ -49,6 +52,7 @@ func (o *Orchestrator) StartFeeders() { } } +// HasRunningFeeder return true if one or more feeders are running func (o *Orchestrator) HasRunningFeeder() bool { rs := RuleSetInstance() for _, rulename := range rs.feedRules { @@ -60,12 +64,14 @@ func (o *Orchestrator) HasRunningFeeder() bool { return false } +// WaitFeeders waits until all the feeders are stopped func (o *Orchestrator) WaitFeeders() { log.Debug("Waiting") o.waitFeeder.Wait() log.Debug("Stop waiting") } +// StopFeeders closes the gates func (o *Orchestrator) StopFeeders() { o.Lock() defer o.Unlock() diff --git a/core/pipe_rule.go b/core/pipe_rule.go index bb3c4b7..47000e1 100644 --- a/core/pipe_rule.go +++ b/core/pipe_rule.go @@ -16,25 +16,28 @@ var ( once sync.Once ) +// Ruleset identifies a set of rules type Ruleset struct { rules map[string]*PipeRule feedRules []string bus bus.Bus - lastId int32 + lastID int32 } +// RuleSetInstance is the singleton for the Ruleset object func RuleSetInstance() *Ruleset { once.Do(func() { instance = &Ruleset{ rules: make(map[string]*PipeRule), bus: bus.New(), - lastId: 0, + lastID: 0, } }) return instance } +// AddRule appends a new rule to the set func (r *Ruleset) AddRule(node *RuleNode, config *Configuration) error { if node == nil || node.Identifier == "" { return fmt.Errorf("Ruleset.AddRule: rules without name are not supported") @@ -58,8 +61,10 @@ func (r *Ruleset) AddRule(node *RuleNode, config *Configuration) error { return nil } +// INode for the nodes generalization type INode interface{} +// PipeRule identifies a single rule type PipeRule struct { Name string HasFeeder bool @@ -121,11 +126,11 @@ func (p *PipeRule) newFilter(fn *FilterNode) (filters.Filter, error) { } rs := RuleSetInstance() - f, err := filters.NewFilter(p.Name, fn.Name+"filter", params, rs.bus, rs.lastId+1, fn.Neg) + f, err := filters.NewFilter(p.Name, fn.Name+"filter", params, rs.bus, rs.lastID+1, fn.Neg) if err != nil { return nil, err } - rs.lastId++ + rs.lastID++ return f, nil } @@ -196,6 +201,7 @@ func (p *PipeRule) addNode(node *Node, prev string) error { return nil } +// NewPipeRule creates and returns a PipeRule struct func NewPipeRule(node *RuleNode, config *Configuration) (*PipeRule, error) { rule := &PipeRule{} rule.Name = node.Identifier @@ -234,12 +240,12 @@ func NewPipeRule(node *RuleNode, config *Configuration) (*PipeRule, error) { } rs := RuleSetInstance() - f, err := feeders.NewFeeder(node.Feeder.Name+"feeder", params, rs.bus, rs.lastId+1) + f, err := feeders.NewFeeder(node.Feeder.Name+"feeder", params, rs.bus, rs.lastID+1) if err != nil { log.Error("piperule.NewRule: %s", err) return nil, err } - rs.lastId++ + rs.lastID++ rule.HasFeeder = true rule.nodes = append(rule.nodes, f) diff --git a/core/rule_parser.go b/core/rule_parser.go index a8dc692..ed49f34 100644 --- a/core/rule_parser.go +++ b/core/rule_parser.go @@ -12,7 +12,6 @@ var ruleLexer = lexer.Must(lexer.Regexp( `(?m)` + `(\s+)` + `|(^[#].*$)` + - `|(?P(?i)FEEDER|SET)` + `|(?P[a-zA-Z][a-zA-Z_\d]*)` + //`|(?P"(?:[^"]*("")?)*")` + `|(?P"(?:\\.|[^\"])*")` + @@ -21,28 +20,33 @@ var ruleLexer = lexer.Must(lexer.Regexp( `|(?P!)`, )) +// AST defines a set of Rules type AST struct { Rules []*RuleNode `@@*` } +// RuleNode defines the first part of the Rule type RuleNode struct { Identifier string `@Ident "="">"` Feeder *FeederNode `( @@` First *Node `| @@ ) ";"` } +// Node identifies a Filter or a RuleCall type Node struct { //Action *ActionNode `( @@ ` Filter *FilterNode `( @@` RuleCall *RuleCall `| @@)` } +// FeederNode identifies the Feeder in the rule type FeederNode struct { Name string `"<" @Ident` Params []*Param `(":" @@ ("," @@)*)? ">"` Next *Node `("|" @@)?` } +// FilterNode identifies the Filter in the rule type FilterNode struct { Neg bool `@("!")?` Name string `@Ident` @@ -56,25 +60,30 @@ type FilterNode struct { // Next *Node `("|" @@)?` //} +// RuleCall identifies the Call nodes in the rule type RuleCall struct { Name string `"@" @Ident` Next *Node `("|" @@)?` } +// Param identifies the parameters accepted by nodes type Param struct { Name string `@Ident "="` Value *Value `@@` } +// Value identifies a String or a Number type Value struct { String *string ` @String` Number *float64 `| @Float` } +// Parser handles the parsing of the rules type Parser struct { handle *participle.Parser } +// NewParser creates a new Parser struct func NewParser() (*Parser, error) { var err error parser := &Parser{} @@ -90,6 +99,7 @@ func NewParser() (*Parser, error) { return parser, nil } +// ParseFile returns the AST of the input file func (p *Parser) ParseFile(filename string) (*AST, error) { ast := &AST{} content, err := ioutil.ReadFile(filename) diff --git a/core/version.go b/core/version.go index f7e8b9d..be89d16 100644 --- a/core/version.go +++ b/core/version.go @@ -1,7 +1,8 @@ package core +// Info on driplane const ( Name = "driplane" - Version = "0.3" + Version = "0.8" Author = "Gianluca Braga aka Matrix86" ) diff --git a/data/message.go b/data/message.go index 6e15268..b98fa03 100644 --- a/data/message.go +++ b/data/message.go @@ -8,18 +8,19 @@ import ( text "text/template" ) -type Callback func(msg Message) - +// Message is the data generated from a Feeder and it travels across Filters type Message struct { sync.RWMutex fields map[string]string } +// NewMessage creates a new Message struct with only the "main" data func NewMessage(msg string) *Message { return NewMessageWithExtra(msg, map[string]string{}) } +// NewMessageWithExtra creates a Message struct with "main" and extra data func NewMessageWithExtra(msg string, extra map[string]string) *Message { extra["main"] = msg return &Message{ @@ -27,18 +28,21 @@ func NewMessageWithExtra(msg string, extra map[string]string) *Message { } } +// SetMessage allows to change the "main" data in the Message struct func (d *Message) SetMessage(msg string) { d.Lock() defer d.Unlock() d.fields["main"] = msg } +// GetMessage returns the "main" data in the Message struct func (d *Message) GetMessage() string { d.RLock() defer d.RUnlock() return d.fields["main"] } +// SetExtra allows to change the "extra" data with key k and value v in the Message struct func (d *Message) SetExtra(k string, v string) { d.Lock() defer d.Unlock() @@ -48,6 +52,7 @@ func (d *Message) SetExtra(k string, v string) { d.fields[k] = v } +// GetExtra returns all the "extra" data in the Message struct func (d *Message) GetExtra() map[string]string { d.Lock() defer d.Unlock() @@ -63,12 +68,14 @@ func (d *Message) GetExtra() map[string]string { return clone } +// SetTarget is like SetExtra but it can change also the "main" key func (d *Message) SetTarget(name string, value string) { d.Lock() defer d.Unlock() d.fields[name] = value } +// GetTarget returns the value of a key in the Message struct. It can return also the "main" data func (d *Message) GetTarget(name string) string { d.RLock() defer d.RUnlock() @@ -78,6 +85,7 @@ func (d *Message) GetTarget(name string) string { return "" } +// Clone creates a deep copy of the Message struct func (d *Message) Clone() *Message { clone := &Message{ fields: make(map[string]string, 0), @@ -89,6 +97,7 @@ func (d *Message) Clone() *Message { return clone } +// ApplyPlaceholder executes the template specified using the data in the Message struct func (d *Message) ApplyPlaceholder(template interface{}) (string, error) { d.RLock() defer d.RUnlock() diff --git a/docs/archetypes/default.md b/docs/archetypes/default.md new file mode 100644 index 0000000..00e77bd --- /dev/null +++ b/docs/archetypes/default.md @@ -0,0 +1,6 @@ +--- +title: "{{ replace .Name "-" " " | title }}" +date: {{ .Date }} +draft: true +--- + diff --git a/docs/config/_default/config.toml b/docs/config/_default/config.toml new file mode 100644 index 0000000..230ab78 --- /dev/null +++ b/docs/config/_default/config.toml @@ -0,0 +1,41 @@ +baseURL = "https://matrix86.github.io/driplane/" +title = "Driplane documentation" +theme = "zdoc" + +defaultContentLanguage = "en" +defaultContentLanguageInSubdir = true +hasCJKLanguage = true + +[author] + name = "Matrix86" + homepage = "https://github.com/Matrix86/" + +copyright = "©{year}, All Rights Reserved" +timeout = 10000 +enableEmoji = true +paginate = 13 +rssLimit = 100 + +googleAnalytics = "" + +[markup] +[markup.goldmark] +[markup.goldmark.renderer] +hardWraps = true +unsafe = true +xHTML = true +[markup.highlight] +codeFences = true +lineNos = true +lineNumbersInTable = true +noClasses = false +[markup.tableOfContents] +endLevel = 4 +ordered = false +startLevel = 2 + +[outputs] +home = ["HTML", "RSS", "JSON"] + +[taxonomies] +tag = "tags" \ No newline at end of file diff --git a/docs/config/_default/languages.toml b/docs/config/_default/languages.toml new file mode 100644 index 0000000..52f52e1 --- /dev/null +++ b/docs/config/_default/languages.toml @@ -0,0 +1,4 @@ +[en] + title = "Dripline Documentation" + languageName = "English" + weight = 1 diff --git a/docs/config/_default/menus.en.toml b/docs/config/_default/menus.en.toml new file mode 100644 index 0000000..13a470d --- /dev/null +++ b/docs/config/_default/menus.en.toml @@ -0,0 +1,5 @@ +[[main]] +identifier = "doc" +name = "Docs" +url = "doc" +weight = 1 \ No newline at end of file diff --git a/docs/config/_default/params.toml b/docs/config/_default/params.toml new file mode 100644 index 0000000..eac5965 --- /dev/null +++ b/docs/config/_default/params.toml @@ -0,0 +1,24 @@ +logo = true # Logo that appears in the site navigation bar. +logoText = "Driplane" # Logo text that appears in the site navigation bar. +logoType = "short" # long, short +description = "Driplane documentation website." # for SEO + +themeOptions = ["light", "dark"] # select options for site color theme + +useFaviconGenerator = true # https://www.favicon-generator.org/ + +enableSearch = true +enableLangChange = false +enableDarkMode = true +enableBreadcrumb = true +enableToc = true +enableMenu = true +enableNavbar = true +enableFooter = false +showPoweredBy = false + +paginateWindow = 1 # setting it to 1 gives 7 buttons, 2 gives 9, etc. If set 1: [1 ... 4 5 6 ... 356] [1 2 3 4 5 ... 356] etc +taxoPaginate = 13 # items per page +taxoGroupByDate = "2006" # "2006-01": group by month, "2006": group by year + +github = "https://github.com/matrix86/driplane" \ No newline at end of file diff --git a/docs/content/_index.md b/docs/content/_index.md index 0d38dcf..f460c0c 100644 --- a/docs/content/_index.md +++ b/docs/content/_index.md @@ -1,126 +1,24 @@ --- -title: Zzo -description: Hugo Zzo theme documentation landing page +author: Gianluca Braga +title: Driplane +description: Driplane site date: 2020-01-26T04:15:05+09:00 draft: false -# updatesBanner: "Banner -   [Hugo ZDoc theme](https://github.com/zzossig/hugo-theme-zdoc)   just arrived" landing: - image: favicon/android-icon-192x192.png + image: favicon/logo192x192.png title: - - Zzo Docs + - Driplane text: - - Make a blog with hugo zzo theme! - titleColor: - textColor: - spaceBetweenTitleText: 25 + - Create automated tasks and keep on eye on interesting things! + titleColor: + textColor: + spaceBetweenTitleText: 30 buttons: - - link: docs/gettingstarted/quickstart + - link: doc text: GET STARTED color: primary - - link: https://github.com/zzossig/hugo-theme-zzo + - link: https://github.com/Matrix86/driplane text: DOWNLOAD color: default -footer: - sections: - - title: General - links: - - title: Docs - link: https://gohugo.io/ - - title: Learn - link: https://gohugo.io/ - - title: Showcase - link: https://gohugo.io/ - - title: Blog - link: https://gohugo.io/ - - title: resources - links: - - title: GitHub - link: https://gohugo.io/ - - title: Releases - link: https://gohugo.io/ - - title: Spectrum - link: https://gohugo.io/ - - title: Telemetry - link: https://gohugo.io/ - - title: Features - links: - - title: GitHub - link: https://gohugo.io/ - - title: Releases - link: https://gohugo.io/ - - title: Spectrum - link: https://gohugo.io/ - - title: Telemetry - link: https://gohugo.io/ - contents: - align: left - applySinglePageCss: false - markdown: - | - ## Zzo docs - Copyright © 2020. All rights reserved. -sections: - - bgcolor: teal - type: card - description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id eleifend erat. Integer eget mattis augue. Suspendisse semper laoreet tortor sed convallis. Nulla ac euismod lorem" - header: - title: Why Zdoc - hlcolor: "#8bc34a" - color: '#fff' - fontSize: 32 - width: 220 - cards: - - subtitle: Performance - subtitlePosition: center - description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id eleifend erat. Integer eget mattis augue." - image: images/section/keyboard.png - color: white - button: - name: Naver - link: https://naver.com - size: large - target: _blank - color: 'white' - bgcolor: '#283593' - - subtitle: Reliability - subtitlePosition: center - description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id eleifend erat. Integer eget mattis augue. Suspendisse semper laoreet tortor sed convallis. Nulla ac euismod lorem" - image: images/section/processor.png - color: white - button: - name: Google - link: https://google.com - size: large - target: _blank - color: 'white' - bgcolor: '#283593' - - subtitle: Productivity - subtitlePosition: center - description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id eleifend erat. Integer eget mattis augue. Suspendisse semper laoreet tortor sed convallis. Nulla ac euismod lorem" - image: images/section/root-server.png - color: white - button: - name: Yahoo - link: https://yahoo.com - size: large - target: _blank - color: 'white' - bgcolor: '#283593' - - bgcolor: DarkSlateBlue - type: normal - description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id eleifend erat. Integer eget mattis augue. Suspendisse semper laoreet tortor sed convallis. Nulla ac euismod lorem" - header: - title: Build it with Zdoc - hlcolor: DarkKhaki - color: "#fff" - fontSize: 32 - width: 340 - body: - subtitle: Extensible and customizable. - subtitlePosition: left - description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce id eleifend erat. Integer eget mattis augue. Suspendisse semper laoreet tortor sed convallis. Nulla ac euismod lorem" - color: white - image: images/section/root-server.png - imagePosition: left --- \ No newline at end of file diff --git a/docs/content/doc/_index.md b/docs/content/doc/_index.md new file mode 100644 index 0000000..8442eb1 --- /dev/null +++ b/docs/content/doc/_index.md @@ -0,0 +1,48 @@ +--- +title: "Driplane Documentation" +description: "Documentation of the Driplane project" +date: 2020-01-11T14:09:21+09:00 +--- + +# Introduction + +Driplane allows you to create an automatic alerting system or start automated tasks triggered by events. +You can keep under control a source as Twitter, a file, a RSS feed or a website. +It includes a mini language to define the filtering pipelines (the rules) and contains a JS plugin system. + +With driplane you can create several rules starting from one or more streams, filter the content in the pipeline and launch task or send e-mail if some events occurred. + +## How it works + +The user can define one or more rules. Each rules contain a source (`feeder`), who cares of get the information and send updates (`Message`) through the pipeline, and several `filters`. +The task of the filters is to propagate or stop the `Message` to the next filter in the pipeline, or change the `Message` received before to propagate it. If the condition is verified, the `Message` will be propagated. + +## Use cases + +Using driplane is it possible to: + + * keep track of keywords or users on Twitter, receive the new tweets or quoted tweet from them, search for URLs or particular strings and send it to a Telegram or Slack channel through a webhook. + * keep track of a RSS feed or a website, and download and store on file all the new changes to them. + +The rules and the JS plugins allows you to create more complex custom logics. + +## Usage + +``` +Usage of driplane: + -config string + Set configuration file. + -debug + Enable debug logs. + -help + This help. + -js string + Path of the js plugins. + -rules string + Path of the rules' directory. +``` + +{{< alert theme="success" >}} + \> driplane -config /path/to/config.yml +{{< /alert >}} + diff --git a/docs/content/doc/configuration/_index.md b/docs/content/doc/configuration/_index.md new file mode 100644 index 0000000..3847c8a --- /dev/null +++ b/docs/content/doc/configuration/_index.md @@ -0,0 +1,44 @@ +--- +weight: 2 +title: "Configuration" +date: 2020-09-16T22:38:03+02:00 +draft: true +--- + +## Configuration + +Driplane needs a yaml file to work. An example can be found [here](https://github.com/Matrix86/driplane/blob/master/config.yaml.example). + +The configuration file could have several sections, but the mandatory one is the `general` one. It specifies all the paths needed by Driplane to find js files, templates and rules. + +> It contains the paths of rules, templates and javascript plugins. + +```yaml +general: + log_path: "" # if nothing is specified it prints logs on stdout + rules_path: "rules" # path containing the rules + js_path: "js" # path of the js plugins + templates_path: "templates" # path of templates + debug: false # if true enable the debug logs +``` + +In the configuration is it possible to define default params for _Feeders_ and _Filters_. In this way we don't need to specify that configuration in the rules. + +> For the twitter feeder we can set the keys one time. +```yaml +twitter: + consumerKey: "consumerKey", + consumerSecret: "consumerSecret", + accessToken: "accessToken", + accessSecret: "accessSecret", + keywords: "#italy #coding #malware something", + stallWarnings: "true" +``` +> Each config will be visible __ONLY__ to the related filter or feeder. + +We can also define `custom` configurations and they'll be available to all the feeders and filters. + +```yaml +custom: + customKey: "This is a custom configuration" +``` \ No newline at end of file diff --git a/docs/content/doc/feeders/_index.md b/docs/content/doc/feeders/_index.md new file mode 100644 index 0000000..9335364 --- /dev/null +++ b/docs/content/doc/feeders/_index.md @@ -0,0 +1,17 @@ +--- +weight: 4 +title: "Feeders" +date: 2020-09-17T11:30:07+02:00 +draft: true +collapsible: true +--- + +# Feeders + +## file + +## rss + +## twitter + +## web diff --git a/docs/content/doc/feeders/file.md b/docs/content/doc/feeders/file.md new file mode 100644 index 0000000..04c5827 --- /dev/null +++ b/docs/content/doc/feeders/file.md @@ -0,0 +1,39 @@ +--- +weight: 1 +title: "File" +date: 2020-09-16T22:38:02+02:00 +draft: false +--- + +## File feeder + +This feeder can create the stream starting from a file. Like the `tail -f` command it opens the specified file and propagates a data message if a line is being added to the file. + +### Parameters + + | Parameter | Type | Default | Description + | --- | --- | --- | --- | + | **filename** | _STRING_ | empty | the path of the file that it has to keep track | + | **toend** | _BOOL_ | "false" | the feeder will start to create data messages only for new added lines | + +{{< notice info "Example" >}} +`... | | ...` +{{< /notice >}} + +### Output + +#### Text + +The `main` field of the Message will contain the new read line. + +#### Extra + +| Name | Description | +| --- | --- | +| file_name | the name of the read file | + +### Examples + +{{< alert theme="warning" >}} +Soon... +{{< /alert >}} \ No newline at end of file diff --git a/docs/content/doc/feeders/rss.md b/docs/content/doc/feeders/rss.md new file mode 100644 index 0000000..3ccdf2b --- /dev/null +++ b/docs/content/doc/feeders/rss.md @@ -0,0 +1,54 @@ +--- +weight: 2 +title: "RSS" +date: 2020-09-16T22:38:02+02:00 +draft: false +--- + +## RSS + +This feeder create a stream starting from a feed `RSS`, `ATOM` or `JSON`. +It is based on [gofeed](https://github.com/mmcdole/gofeed) so you can refer to it for more info and supported formats. + +### Parameters + + | Parameter | Type | Default | Description + | --- | --- | --- | --- | + | **url** | _STRING_ | empty | URL of the feed | + | **freq** | _[DURATION](https://golang.org/pkg/time/#ParseDuration)_ | 60s | how often the feed should be parsed | + | **start_from_beginning** | _BOOL_ | "false" | start to parse from the beginning of the feed | + +{{< notice info "Example" >}} +`... | | ...` +{{< /notice >}} + +### Output + +#### Text + +The `main` field of the Message will contain the `item.Title` string of the `gofeed.Item` struct. + +#### Extra + +| Name | Description | +| --- | --- | +| feed_title | title of the feed ([feed.Title](https://github.com/mmcdole/gofeed#default-mappings)) | +| feed_feedlink | feed url ([feed.FeedLink](https://github.com/mmcdole/gofeed#default-mappings)) | +| feed_updated | time of the last update ([feed.Updated](https://github.com/mmcdole/gofeed#default-mappings)) | +| feed_published | date of publication ([feed.Published](https://github.com/mmcdole/gofeed#default-mappings)) | +| feed_author | author in the form `name ` ([feed.Author.Name](https://github.com/mmcdole/gofeed#default-mappings)) | +| feed_language | language of the feed ([feed.Language](https://github.com/mmcdole/gofeed#default-mappings)) | +| feed_copyright | copyright ([feed.Copyright](https://github.com/mmcdole/gofeed#default-mappings)) | +| feed_generator | generator used to create the feed ([feed.Generator](https://github.com/mmcdole/gofeed#default-mappings)) | + +In addiction to the feed tags, the Extra will also contain the item's fields. Since they could be different from feed to feed and it is possible to configure custom tag, you'll find all them in the extra with their name. + +{{< notice warning "ATTENTION" >}} +Not all the Extra field could be filled. If the relative tag is not present on the feed it will be empty. +{{< /notice >}} + +### Examples + +{{< alert theme="warning" >}} +Soon... +{{< /alert >}} \ No newline at end of file diff --git a/docs/content/doc/feeders/twitter.md b/docs/content/doc/feeders/twitter.md new file mode 100644 index 0000000..4dd0fc2 --- /dev/null +++ b/docs/content/doc/feeders/twitter.md @@ -0,0 +1,63 @@ +--- +weight: 3 +title: "Twitter" +date: 2020-09-16T22:38:02+02:00 +draft: false +--- + +## Twitter + +This feeder creates a stream from tweets. It is possible to define the keywords, or the users to follow. +Based on [go-twitter](https://github.com/dghubble/go-twitter) + +### Parameters + + | Parameter | Type | Default | Description + | --- | --- | --- | --- | + | **consumerKey** | _STRING_ | empty | [Twitter Auth](https://developer.twitter.com/en/docs/twitter-api/getting-started/guide) | + | **consumerSecret** | _STRING_ | empty | [Twitter Auth](https://developer.twitter.com/en/docs/twitter-api/getting-started/guide) | + | **accessToken** | _STRING_ | empty | [Twitter Auth](https://developer.twitter.com/en/docs/twitter-api/getting-started/guide) | + | **accessSecret** | _STRING_ | empty | [Twitter Auth](https://developer.twitter.com/en/docs/twitter-api/getting-started/guide) | + | **keywords** | _STRING_ | empty | comma separated keywords that should match on the tweets | + | **users** | _STRING_ | empty | comma separated users list | + | **languages** | _STRING_ | empty | filter by language | + | **disable_retweet** | _BOOL_ | "false" | don't include retweets in the stream | + | **disable_quoted** | _BOOL_ | "false" | don't include quoted tweets in the stream | + +{{< notice info "Example" >}} +`... | | ...` +{{< /notice >}} + +### Output + +#### Text + +The `main` field of the Message will contain: + + * the text of the tweet if it is a normal tweet; + * the text of the retweeted message if it is a retweet; + * the text of the quote if it is a quote tweet; + +#### Extra + +| Name | Description | +| --- | --- | +| link | link to the tweet | +| language | language used for the tweet | +| username | author of the tweet | +| quoted | "true" if the tweet if a quoted tweet, "false" otherwise | +| retweet | "true" if the tweet if a retweeted tweet, "false" otherwise | +| original_username | author of the original tweet if it is a retweet or quoted tweet | +| original_language | language of the original tweet if it is a retweet or quoted tweet | +| original_status | text of the original tweet if it is a retweet or quoted tweet | +| original_link | link of the original tweet if it is a retweet or quoted tweet | + +{{< notice warning "ATTENTION" >}} +In some circumstances the extra field could be empty. +{{< /notice >}} + +### Examples + +{{< alert theme="warning" >}} +Soon... +{{< /alert >}} \ No newline at end of file diff --git a/docs/content/doc/feeders/web.md b/docs/content/doc/feeders/web.md new file mode 100644 index 0000000..5fcac6d --- /dev/null +++ b/docs/content/doc/feeders/web.md @@ -0,0 +1,55 @@ +--- +weight: 4 +title: "Web" +date: 2020-09-16T22:38:02+02:00 +draft: false +--- + +## Web + +This feeder creates a stream starting from a web page. It is possible to define how often the page should be downloaded and parsed. +Every time the page is parsed a Message is sent down the lane. + +### Parameters + + | Parameter | Type | Default | Description + | --- | --- | --- | --- | + | **url** | _STRING_ | empty | URL of the web page | + | **freq** | _[DURATION](https://golang.org/pkg/time/#ParseDuration)_ | 60s | how often the page should be parsed | + | **text_only** | _BOOL_ | "false" | if "true" it removes all the tags from the page | + | **method** | _STRING_ | "GET" | HTTP method to use on the requests | + | **headers** | _JSON_ | empty | Headers to use in the request | + | **data** | _JSON_ | empty | POST fields to send with the requests (it's not possible to use in combination with `rawData`) | + | **rawData** | _STRING_ | empty | raw body of the requests (it's not possible to use in combination with `data`) | + | **status** | _STRING_ | empty | the filter will propagate the Message only if the returned status is this | + | **cookies** | _STRING_ | empty | Path of the JSON file containing the cookies to use | + +{{< notice info "Example" >}} +`... | | ...` +{{< /notice >}} + +### Output + +#### Text + +The `main` field of the Message will contain the HTML source or the text of the website if the `text_only` parameter is set to true. + +#### Extra + +| Name | Description | +| --- | --- | +| url | URL of the web page | +| title | meta tag `title` | +| description | meta tag `description` | +| image | meta tag `image` | +| sitename | meta tag `sitename` | + +{{< notice warning "ATTENTION" >}} +Not all the Extra field could be filled. If the relative tag is not present on the feed it will be empty. +{{< /notice >}} + +### Examples + +{{< alert theme="warning" >}} +Soon... +{{< /alert >}} \ No newline at end of file diff --git a/docs/content/doc/filters/_index.md b/docs/content/doc/filters/_index.md new file mode 100644 index 0000000..8d7548c --- /dev/null +++ b/docs/content/doc/filters/_index.md @@ -0,0 +1,7 @@ +--- +weight: 5 +title: "Filters" +date: 2020-09-17T11:30:11+02:00 +draft: true +collapsible: true +--- diff --git a/docs/content/doc/filters/cache.md b/docs/content/doc/filters/cache.md new file mode 100644 index 0000000..f2a7848 --- /dev/null +++ b/docs/content/doc/filters/cache.md @@ -0,0 +1,35 @@ +--- +weight: 1 +title: "Cache" +date: 2020-09-16T22:38:02+02:00 +draft: false +--- + +## Cache + +This filter introduces a simple cache mechanism in the rule. It is a TTL based cache and it can have a local visibility (cache is only visible to the current filter) or a global visibility (cache shared across **ALL** the rules). +If the target of the Message as input has been cached before, and his TTL is not expired, it will be dropped and not propagated to the next filter. +Otherwise if the target of the Message is new to the cache, it is inserted in it and propagated to the next filter. + +### Parameters + + | Parameter | Type | Default | Description + | --- | --- | --- | --- | + | **target** | _STRING_ | "main" | the field of the Message that should be used for the filter (it could be main or and extra field) | + | **refresh_on_get** | _BOOL_ | "true" | the TTL is refreshed if the key has been looked up | + | **ttl** | _[DURATION](https://golang.org/pkg/time/#ParseDuration)_ | 24h | how long after the key will be deleted | + | **global** | _BOOL_ | "false" | make this cache global | + +{{< notice info "Example" >}} +`... | cache(ttl="24h", global="true") | ...` +{{< /notice >}} + +### Output + +The output is not be changed. This filter can only stop or not the propagation of the Message. + +### Examples + +{{< alert theme="warning" >}} +Soon... +{{< /alert >}} \ No newline at end of file diff --git a/docs/content/doc/filters/changed.md b/docs/content/doc/filters/changed.md new file mode 100644 index 0000000..1d32f81 --- /dev/null +++ b/docs/content/doc/filters/changed.md @@ -0,0 +1,30 @@ +--- +weight: 2 +title: "Changed" +date: 2020-09-16T22:38:02+02:00 +draft: false +--- + +## Changed + +This filter is similar to the cache. It can only stop the propagation of the Message across the lane, but only if the target of the received Message is different from the previous one. + +### Parameters + + | Parameter | Type | Default | Description + | --- | --- | --- | --- | + | **target** | _STRING_ | "main" | the field of the Message that should be used for the filter (it could be main or and extra field) | + +{{< notice info "Example" >}} +`... | changed(target="original_author") | ...` +{{< /notice >}} + +### Output + +The output is not be changed. This filter can only stop or not the propagation of the Message. + +### Examples + +{{< alert theme="warning" >}} +Soon... +{{< /alert >}} \ No newline at end of file diff --git a/docs/content/doc/filters/echo.md b/docs/content/doc/filters/echo.md new file mode 100644 index 0000000..5661faa --- /dev/null +++ b/docs/content/doc/filters/echo.md @@ -0,0 +1,30 @@ +--- +weight: 3 +title: "Echo" +date: 2020-09-16T22:38:02+02:00 +draft: false +--- + +## Echo + +This filter print the Message on the logs. Mostly used to debug the rules. + +### Parameters + + | Parameter | Type | Default | Description + | --- | --- | --- | --- | + | **extra** | _BOOL_ | "false" | print also all the extra fields | + +{{< notice info "Example" >}} +`... | echo(extra="false") | ...` +{{< /notice >}} + +### Output + +The output is not be changed. This filter prints the received Message and send it to the next filter in the rule. + +### Examples + +{{< alert theme="warning" >}} +Soon... +{{< /alert >}} \ No newline at end of file diff --git a/docs/content/doc/filters/format.md b/docs/content/doc/filters/format.md new file mode 100644 index 0000000..4b50812 --- /dev/null +++ b/docs/content/doc/filters/format.md @@ -0,0 +1,36 @@ +--- +weight: 4 +title: "Format" +date: 2020-09-16T22:38:02+02:00 +draft: false +--- + +## Format + +This filter is used to format the received Message. It is based on the [Golang templates](https://golang.org/pkg/text/template/) it can load templates from the `template_path` directory specified in the configuration file. + +### Parameters + + | Parameter | Type | Default | Description + | --- | --- | --- | --- | + | **type** | _STRING_ | "text" | specify the type of template to use : `"text"` or `"html"` | + | **template** | _STRING_ | empty | a template could be specified directly here, instead of load it from file | + | **file** | _STRING_ | empty | load the template from file | + +In the template is allowed to use all the fields of the received Message: main or extra. + +{{< notice info "Example" >}} +`... | format(type="html", template="main : {{.main}} extra : {{.file_name}}") | ...` +{{< /notice >}} + + + +### Output + +The new formatted text is sent to the next filter in the `main` field of the Message. The extra fields don't undergo changes. + +### Examples + +{{< alert theme="warning" >}} +Soon... +{{< /alert >}} \ No newline at end of file diff --git a/docs/content/doc/filters/hash.md b/docs/content/doc/filters/hash.md new file mode 100644 index 0000000..cef0e7c --- /dev/null +++ b/docs/content/doc/filters/hash.md @@ -0,0 +1,48 @@ +--- +weight: 5 +title: "Hash" +date: 2020-09-16T22:38:02+02:00 +draft: false +--- + +## Hash + +This filter is used to search or extract hashes from a Message. +Supported types of hashes are: + * MD5 + * SHA1 + * SHA256 + * SHA512 + +### Parameters + + | Parameter | Type | Default | Description + | --- | --- | --- | --- | + | **target** | _STRING_ | "main" | the field of the Message that should be used for the filter (it could be main or an extra field) | + | **extract** | _BOOL_ | "false" | if `"true"` the main field of the output Message will be the extracted hash | + | **md5** | _BOOL_ | "true" | if `"false"` md5 hashes will be ignored | + | **sha1** | _BOOL_ | "true" | if `"false"` sha1 hashes will be ignored | + | **sha256** | _BOOL_ | "true" | if `"false"` sha256 hashes will be ignored | + | **sha512** | _BOOL_ | "true" | if `"false"` sha512 hashes will be ignored | + + +{{< notice info "Example" >}} +`... | hash(target="description", extract="true") | ...` +{{< /notice >}} + +### Output + +If the `extract` parameter is "false", the received Message will be propagated only if at least a hash is found in it. +Otherwise if `extract` is "true" and the Message contains one or more hashes, the `main` field of the propagated Message will contain only the extracted hash. + +If the `extract` parameter is "true" and the message is propagated, a new extra field is created: `fulltext` will contain the original `target` string. + +{{< notice warning "ATTENTION" >}} +If the targeted field contains multiple hashes, the filter will create and propagate multiple messages, one for each hash. +{{< /notice >}} + +### Examples + +{{< alert theme="warning" >}} +Soon... +{{< /alert >}} \ No newline at end of file diff --git a/docs/content/doc/filters/http.md b/docs/content/doc/filters/http.md new file mode 100644 index 0000000..580bcaf --- /dev/null +++ b/docs/content/doc/filters/http.md @@ -0,0 +1,43 @@ +--- +weight: 6 +title: "Http" +date: 2020-09-16T22:38:02+02:00 +draft: false +--- + +## HTTP + +This filter allows you to send HTTP requests. When a `Message` arrives to the filter, we can decide if use the `main` field of the `Message` as URL on the request, or its content for the HTTP data. +This behaviour can be handle with the parameters. + +### Parameters + + | Parameter | Type | Default | Description + | --- | --- | --- | --- | + | **url** | _STRING_ | empty | URL of the web page. It is possible use the [Golang templates](https://golang.org/pkg/text/template/) to use fields of the `Message` | + | **text_only** | _BOOL_ | "false" | if "true" it removes all the tags from the body response | + | **method** | _STRING_ | "GET" | HTTP method to use on the request | + | **headers** | _JSON_ | empty | Headers to use in the request | + | **data** | _JSON_ | empty | POST fields to send with the request (it's not possible to use in combination with `rawData`) | + | **rawData** | _STRING_ | empty | raw body of the request (it's not possible to use in combination with `data`) | + | **status** | _STRING_ | empty | the filter will propagate the Message only if the returned status has the specified value | + | **cookies** | _STRING_ | empty | Path of the JSON file containing the cookies to use | + + +{{< notice info "Example" >}} +`... | http(url="{{ .main }}", cookies="exported.json", headers="{\"Content-type\": \"application/json\"}") | ...` +{{< /notice >}} + +### Output + +If the request was successful, the output `Message` will have the `main` field set to the HTTP body response. If the `status` is set, and the response http status is different from it, the `Message` will be dropped. + +{{< notice warning "ATTENTION" >}} +The `Message` is dropped if the request is failed. +{{< /notice >}} + +### Examples + +{{< alert theme="warning" >}} +Soon... +{{< /alert >}} \ No newline at end of file diff --git a/docs/content/doc/filters/js/_index.md b/docs/content/doc/filters/js/_index.md new file mode 100644 index 0000000..6c3f1fe --- /dev/null +++ b/docs/content/doc/filters/js/_index.md @@ -0,0 +1,8 @@ +--- +weight: 12 +title: "JS" +date: 2020-09-16T22:38:02+02:00 +draft: false +collapsible: true +--- + \ No newline at end of file diff --git a/docs/content/doc/filters/js/basics.md b/docs/content/doc/filters/js/basics.md new file mode 100644 index 0000000..3c7d47e --- /dev/null +++ b/docs/content/doc/filters/js/basics.md @@ -0,0 +1,32 @@ +--- +weight: 1 +title: "Basics" +date: 2020-09-16T22:38:02+02:00 +draft: false +--- + +## JS + +This filter allows to extend the basic driplane's filter, defining Javascript scripts. It is based on [islazy/plugin](https://github.com/evilsocket/islazy) that is based on [robertkrimen/otto](https://github.com/robertkrimen/otto). +Defining a JS file with our custom logic, it is possible create a complex filter. + +### Parameters + + | Parameter | Type | Default | Description + | --- | --- | --- | --- | + | **path** | _STRING_ | empty | path of the Javascript file (it can contains multiple functions) | + | **function** | _STRING_ | empty | name of the function in the JS file to call when a `Message` is received | + +{{< notice info "Example" >}} +`... | js(path="script.js", function="MyFunction") | ...` +{{< /notice >}} + +### Output + +The output `Message` of this filter depends on the return value of the JS function itself. + +### Examples + +{{< alert theme="warning" >}} +Soon... +{{< /alert >}} \ No newline at end of file diff --git a/docs/content/doc/filters/js/entrypoint.md b/docs/content/doc/filters/js/entrypoint.md new file mode 100644 index 0000000..6eca672 --- /dev/null +++ b/docs/content/doc/filters/js/entrypoint.md @@ -0,0 +1,52 @@ +--- +weight: 2 +title: "Entrypoint" +date: 2020-09-16T22:38:02+02:00 +draft: false +--- + +## Entrypoint + +The JS file should consist of one or more functions, and they can be used in different filters or in combination between them. +The function has to respect some constraints: + + * the function's name contained in the `function` parameter of the filter has to start with a capital letter; + * the function prototype should accept 3 variables; + * the function has to return a JS object with at least the `filtered` field; + +### Function's prototype + +The function's name specified in the `function` parameter of the filter, receives 3 input parameters: + * main: it is a string with the content of the field `main` of the input Message; + * extra: a JS object that can be seen like an associative array, containing the extra fields of the input Message; + * params: a JS object like the previous, but it contains the configurations from the `custom` and the `general` sections. + +So for example we can define a function like the follow: + +```javascript +function Entry(main, extra, params) { + ... +} +``` + +### Return value + +The JS function has to return a value back to the filter, so that the filter can use it to propagate the Message or drop it. +The method used on `function` parameter can return a JS object containing at least the `filtered` field. +If this field has been set to true, the `Message` will be sent to the next filter, otherwise if the `filtered` field has been set to false, the filter will drop the Message. + +We would change the fields of the `Message`, and to do that we can use the `data` field in the returned object. +It should be an associative array and it will be mapped in a map[string]string object in the Go env. +The key of the array's row is the name of the field to add or change, while the value is the string that field's Message will contain after the return. + +```javascript +function Entry(mainData, extra, params) { + return { + "filtered": true, + "data": { + "main": "main field of the input Message changed", + "new_field": "new_field will be added as Message's extra field" + } + }; +} +``` \ No newline at end of file diff --git a/docs/content/doc/filters/js/packages.md b/docs/content/doc/filters/js/packages.md new file mode 100644 index 0000000..77c1fdb --- /dev/null +++ b/docs/content/doc/filters/js/packages.md @@ -0,0 +1,120 @@ +--- +weight: 2 +title: "Plugin Packages" +date: 2020-09-16T22:38:02+02:00 +draft: false +--- + +## Packages + +Since the JS doesn't have all the useful functions to perform operations like on file manipulation or http request (see [otto docs](https://godoc.org/github.com/robertkrimen/otto) for more info), driplane maps and export to the JS environment some Go functions as packages. + + +{{< alert theme="warning" >}} +These mapped functions are not definitive and they could change over time. +{{< /alert >}} + +### File + +This package contains functions for manipulating files. + +#### Return + +The return value will be a JS object containing 2 fields: + +| Name | Type | Description | +| --- | --- | --- | +| Status | _BOOL_ | if true the operation was successful | +| Error | _STRING_ | if status is false it contains the reason of the failure | + +#### Functions + +| Prototype | Description | +| --- | --- | +| file.Move(src string, dest string) | Move the file `src` to the new position `dest` | +| file.Copy(src string, dest string) | Copy the file `src` to the position `dest` | +| file.Truncate(filename string, size int) | set or adjust the file called `filename` by `size` bytes | +| file.Delete(filename string) | Remove the file called `filename` | +| file.Exists(filename string) | Return Status = true if `filename` exists on disk | +| file.AppendString(filename string, text string) | Append the string `text` to the file `filename` | + +### Log + +This package contains functions for writing strings on the logs. + +#### Return + +It doesn't have a return value. + +#### Functions + +| Prototype | Description | +| --- | --- | +| log.Info(format string, ...) | Write an Info line on the log | +| log.Error(src string, ...) | Write an Error line on the log | +| log.Debug(src string, ...) | Write a Debug line on the log | + +### Strings + +This package contains functions for manipulating strings. + +#### Return + +The return value will be a JS object containing 2 fields: + +| Name | Type | Description | +| --- | --- | --- | +| Status | _BOOL_ | if true the operation was successful | +| Error | _STRING_ | if status is false it contains the reason of the failure | + +#### Functions + +| Prototype | Description | +| --- | --- | +| strings.StartsWith(str string, substr string) | Status = true if `str` start with `substr` | + +### Util + +This package contains miscellaneous functions. + +#### Return + +The return value will be a JS object containing 2 fields: + +| Name | Type | Description | +| --- | --- | --- | +| Status | _BOOL_ | if true the operation was successful | +| Error | _STRING_ | if status is false it contains the reason of the failure | +| Value | _STRING_ | this string contains the returned value | + +#### Functions + +| Prototype | Description | +| --- | --- | +| util.Sleep(seconds int) | wait for `seconds` seconds | +| util.Getenv(name string) | get the value of the `name` environment variables, if it exists, and return it on the `Value` field of the returned value | + +### Http + +This package contains functions to perform HTTP requests. + +#### Return + +The return value will be a JS object containing 4 fields: + +| Name | Type | Description | +| --- | --- | --- | +| Status | _BOOL_ | if true the operation was successful | +| Error | _STRING_ | if status is false it contains the reason of the failure | +| Response | _OBJECT_ | it returns the [http.Response](https://golang.org/pkg/net/http/#Response) object | +| Body | _STRING_ | it contains the body of the response converted in string | + +#### Functions + +| Prototype | Description | +| --- | --- | +| http.Request(method string, uri string, headers interface{}, data interface{}) | | +| http.Get(url string, headers map[string]string) | | +| http.Post(url string, headers map[string]string, data interface{}) | | +| http.DownloadFile(filepath string, method string, uri string, headers interface{}, data interface{}) | | +| http.UploadFile(filename string, fieldname string, method string, uri string, headers interface{}, data interface{}) | | diff --git a/docs/content/doc/filters/mail.md b/docs/content/doc/filters/mail.md new file mode 100644 index 0000000..8b83fee --- /dev/null +++ b/docs/content/doc/filters/mail.md @@ -0,0 +1,46 @@ +--- +weight: 7 +title: "Mail" +date: 2020-09-16T22:38:02+02:00 +draft: false +--- + +## Mail + +This filter allows you to send e-mail. When a `Message` arrives to the filter, we can decide if use the `main` field of the `Message` as URL on the request, or its content for the HTTP data. +This behaviour can be handle with the parameters. + +### Parameters + + | Parameter | Type | Default | Description + | --- | --- | --- | --- | + | **body** | _STRING_ | empty | the body of the e-mail (supports [Golang templates](https://golang.org/pkg/text/template/)) | + | **username** | _STRING_ | empty | username for the host authentication | + | **password** | _STRING_ | empty | password for the host authentication | + | **host** | _STRING_ | empty | host server used to send the e-mail | + | **port** | _STRING_ | empty | port of the host server | + | **fromAddr** | _STRING_ | empty | source e-mail address | + | **fromName** | _STRING_ | empty | source name address | + | **to** | _STRING_ | empty | destination e-mail address (supports multi-destination, comma separated) | + | **subject** | _STRING_ | empty | subject field of the e-mail to send | + | **use_auth** | _BOOL_ | "false" | if "true" the sendmail server will receive the credentials specified in `username` and `password` fields | + + +{{< notice info "Example" >}} +`... | http(url="{{ .main }}", cookies="exported.json", headers="{\"Content-type\": \"application/json\"}") | ...` +{{< /notice >}} + +{{< notice success "Remember" >}} +Every default value can be set in the configuration, creating a section with the name of the`Filter`/`Feeder`. +[more info](../../configuration) +{{< /notice >}} + +### Output + +The input `Message` is always propagated to the next filter without changes. + +### Examples + +{{< alert theme="warning" >}} +Soon... +{{< /alert >}} \ No newline at end of file diff --git a/docs/content/doc/filters/override.md b/docs/content/doc/filters/override.md new file mode 100644 index 0000000..7989453 --- /dev/null +++ b/docs/content/doc/filters/override.md @@ -0,0 +1,32 @@ +--- +weight: 8 +title: "Override" +date: 2020-09-16T22:38:02+02:00 +draft: false +--- + +## Override + +This filter allows you to change a field of a Message, before to sent it to the next filter. Template can be used. + +### Parameters + + | Parameter | Type | Default | Description + | --- | --- | --- | --- | + | **name** | _STRING_ | empty | name of the field to change (supports [Golang templates](https://golang.org/pkg/text/template/)) | + | **value** | _STRING_ | empty | new value to assign to the Message's field specified (supports [Golang templates](https://golang.org/pkg/text/template/)) | + + +{{< notice info "Example" >}} +`... | override(name="description", value="{{ .title }}") | ...` +{{< /notice >}} + +### Output + +The propagated Message will be identical to the original, with only the specified field changed. + +### Examples + +{{< alert theme="warning" >}} +Soon... +{{< /alert >}} \ No newline at end of file diff --git a/docs/content/doc/filters/system.md b/docs/content/doc/filters/system.md new file mode 100644 index 0000000..7ad3712 --- /dev/null +++ b/docs/content/doc/filters/system.md @@ -0,0 +1,32 @@ +--- +weight: 9 +title: "System" +date: 2020-09-16T22:38:02+02:00 +draft: false +--- + +## System + +This filter allows you to exec a command on the host machine. The received Message can be used to create the command to launch. +It supports [Golang templates](https://golang.org/pkg/text/template/) (only text.Template). + +### Parameters + + | Parameter | Type | Default | Description + | --- | --- | --- | --- | + | **cmd** | _STRING_ | empty | command line to exec for each received Message (supports [Golang templates](https://golang.org/pkg/text/template/)) | + + +{{< notice info "Example" >}} +`... | system(cmd="echo '{{ .author }} wrote {{ .main }}' >> logs.txt") | ...` +{{< /notice >}} + +### Output + +The propagated Message will contain the output of the command (if it is there) if it is not failed. + +### Examples + +{{< alert theme="warning" >}} +Soon... +{{< /alert >}} \ No newline at end of file diff --git a/docs/content/doc/filters/text.md b/docs/content/doc/filters/text.md new file mode 100644 index 0000000..45d71da --- /dev/null +++ b/docs/content/doc/filters/text.md @@ -0,0 +1,42 @@ +--- +weight: 10 +title: "Text" +date: 2020-09-16T22:38:02+02:00 +draft: false +--- + +## Text + +This filter searches or extracts strings from the received Message. It can be used with a regular expression or a simple string. +If the string is found, the condition is matched and the Message is propagated to the next filter. + +### Parameters + + | Parameter | Type | Default | Description + | --- | --- | --- | --- | + | **target** | _STRING_ | "main" | the field of the Message that should be used for the filter (it could be main or and extra field) | + | **regexp** | _STRING_ | empty | regular expression to search or extract one or more strings | + | **extract** | _BOOL_ | "false" | if "true" the `main` field of the propagated Message will contain the extracted string (it can be used only if `regexp` parameter is specified) | + | **text** | _STRING_ | specifies the string that should be matched on the Message to check the condition | + + +{{< notice info "Example" >}} +`... | text(target="description", regexp="(#[^\\s]+)", extract="true") | ...` +{{< /notice >}} + +### Output + +If the `extract` parameter is "false", the received Message will be propagated only if the specified `text` or `regexp` is matched in the `target` field of the Message. +Otherwise if `extract` is "true" (only `regexp` can be used in this case), and one or more strings matches with the `regexp` filter, the `main` field of the propagated Message will contain only the matched string. + +If the `extract` parameter is "true" and the message is propagated, a new extra field is created: `fulltext` will contain the original `target` string. + +{{< notice warning "ATTENTION" >}} +If the targeted field contains multiple matches, the filter will create and propagate multiple Messages, one for each matched string. +{{< /notice >}} + +### Examples + +{{< alert theme="warning" >}} +Soon... +{{< /alert >}} \ No newline at end of file diff --git a/docs/content/doc/filters/url.md b/docs/content/doc/filters/url.md new file mode 100644 index 0000000..13f4102 --- /dev/null +++ b/docs/content/doc/filters/url.md @@ -0,0 +1,45 @@ +--- +weight: 11 +title: "Url" +date: 2020-09-16T22:38:02+02:00 +draft: false +--- + +## Url + +This filter is used to search or extract URLs from a Message. +Currently supported types of URLs are: + * http/s + * ftp + +### Parameters + + | Parameter | Type | Default | Description + | --- | --- | --- | --- | + | **target** | _STRING_ | "main" | the field of the Message that should be used for the filter (it could be main or an extra field) | + | **http** | _BOOL_ | "true" | if "false", `http` scheme urls are ignored | + | **https** | _BOOL_ | "true" | if "false", `https` scheme urls are ignored | + | **ftp** | _BOOL_ | "true" | if "false", `ftp` scheme urls are ignored | + | **extract** | _BOOL_ | "true" | if "true", the `main` field of the propagated Message will contain the found URL | + + +{{< notice info "Example" >}} +`... | url(extract="true") | ...` +{{< /notice >}} + +### Output + +If the `extract` parameter is "false", the received Message will be propagated only if at least an URL will be found in it. +Otherwise if `extract` is "true" and the Message contains one or more URLs, the `main` field of the propagated Message will contain only the extracted URLs. + +If the `extract` parameter is "true" and the message is propagated, a new extra field is created: `fulltext` will contain the original `target` string. + +{{< notice warning "ATTENTION" >}} +If the targeted field contains multiple URLs, the filter will create and propagate multiple messages, one for each URL. +{{< /notice >}} + +### Examples + +{{< alert theme="warning" >}} +Soon... +{{< /alert >}} \ No newline at end of file diff --git a/docs/content/doc/installation/_index.md b/docs/content/doc/installation/_index.md new file mode 100644 index 0000000..ddfc73e --- /dev/null +++ b/docs/content/doc/installation/_index.md @@ -0,0 +1,8 @@ +--- +weight: 1 +title: "Installation" +date: 2020-09-16T22:38:02+02:00 +draft: false +collapsible: true +--- + diff --git a/docs/content/doc/installation/build.md b/docs/content/doc/installation/build.md new file mode 100644 index 0000000..715587b --- /dev/null +++ b/docs/content/doc/installation/build.md @@ -0,0 +1,14 @@ +--- +weight: 1 +title: "Build and install" +date: 2020-09-16T22:38:02+02:00 +draft: false +--- + +## Build and install + +Launching the follow command go will take care of the downloading, the dependency resolving, the building and finally of the installation of the binary in the _$GOBIN_ directory. + +{{< alert theme="success" >}} +go get -u github.com/Matrix86/driplane/... +{{< /alert >}} diff --git a/docs/content/doc/installation/docker.md b/docs/content/doc/installation/docker.md new file mode 100644 index 0000000..227e5f9 --- /dev/null +++ b/docs/content/doc/installation/docker.md @@ -0,0 +1,12 @@ +--- +weight: 2 +title: "Docker" +date: 2020-09-16T22:38:02+02:00 +draft: false +--- + +## Docker + +{{< alert theme="warning" >}} +Soon... +{{< /alert >}} \ No newline at end of file diff --git a/docs/content/doc/rules/_index.md b/docs/content/doc/rules/_index.md new file mode 100644 index 0000000..c7115e9 --- /dev/null +++ b/docs/content/doc/rules/_index.md @@ -0,0 +1,7 @@ +--- +weight: 3 +title: "Rules" +date: 2020-09-17T11:29:50+02:00 +draft: true +collapsible: true +--- \ No newline at end of file diff --git a/docs/content/doc/rules/definition.md b/docs/content/doc/rules/definition.md new file mode 100644 index 0000000..f86e1f2 --- /dev/null +++ b/docs/content/doc/rules/definition.md @@ -0,0 +1,20 @@ +--- +weight: 1 +title: "First look" +date: 2020-09-16T22:38:02+02:00 +draft: false +--- + +## First look + +Driplane include a simple language to define where get the stream and what operation exec, or how to filter the data. + +In the rule could be defined 3 type of nodes: + +* `FEEDER` : it is the node responsible for creating of a stream of data (read every changes on a file, get tweets from Twitter, etc..) + +* `FILTER` : it receives data from a feeder or another filter and checks some conditions on them or makes some changes on them. It send the data to the next filter **ONLY** if the condition is verified. + +* `RULE CALL` : every rule has a name, so you can define a rule with a preset feeder or a pipe of filters and connect to another filter/feeder. + +It is possible to define custom parameters for feeders or filters. Each one of them has a different type of parameters that can change their behaviour and you can find a list of them in the related section. \ No newline at end of file diff --git a/docs/content/doc/rules/syntax.md b/docs/content/doc/rules/syntax.md new file mode 100644 index 0000000..cee1126 --- /dev/null +++ b/docs/content/doc/rules/syntax.md @@ -0,0 +1,76 @@ +--- +weight: 2 +title: "Syntax" +date: 2020-09-16T22:38:02+02:00 +draft: false +--- + +## Syntax + +The syntax of the driplane's rules is really simple. Like for the BASH every filter's output is sended to the next filter's input concatenating the two of them with the `|` character. +All the rules have to start with a name and end with a `;` char. + +### Rule Name and Rule Call + +Each rule have to start with an identifier follow by `=>`. This identifier identifies _rule name_ and it could be used in another rule to concatenate 2 rule together. + +{{< notice warning "ATTENTION" >}} +This name has to be **unique** in the rules. +{{< /notice >}} + +> Example: +> `IDENTIFIER => ... ;` + +It can be included in another rule (**rule call**) prepending the `@` to it. + +> Example: +> `IDENTIFIER1 => ... ;` +> `IDENTIFIER2 => ... | @IDENTIFIER1 | ... ;` + +### Feeder + +The feeder creates the stream, so they don't accept inputs. For this they can be positioned **ONLY** to the beginning of a rule. + +The feeder definition starts with a `<` char followed by an identifier. That's the type of the feeder we want to use. + +After the type we found a `:` char followed by a list of **parameters** comma separated and a `>`. + +{{< notice info "Parameters" >}} +The parameters are in the form of key/value where the value is between double quotes `key="value"`. +{{< /notice >}} + +> Example: +> `IDENTIFIER => | ... ;` + +### Filter + +The filter are the main operators of a rule, because they decide if a data is interesting and perform operations. + +The definition of a filter start with his name and it is followed by parameters contained between `(` and `)`. +According to the settings a Filter can change his behaviour and can modify the data passing through it. + +> Example: +> `IDENTIFIER => ... | FILTER_TYPE( param1="value1", ... ) | ... ;` + +{{< notice info "NOT" >}} +The operator **NOT** `!` can be used on filter to negate his result (propagate the data if the condition is not verified). +It has to be put before the filter definition: `!FILTER_TYPE(...)` +{{< /notice >}} + +{{< notice warning "ATTENTION" >}} +All the parameters have to be enclosed in quotes. +JSON requires **double quotes** to encode strings, so in order to define a JSON string you need to escape the quotes `\"`. +{{< /notice >}} + +### Data message and Extra + +The data stream in driplane is based on text and the basic object that is part of it is the _Message_. +The _Message_ is an object that contains the text that need to be filtered and extra. +The main string is identified as `text` in the filters, whereas the extra data are identified by a key. + +There are fixed extra, created from driplane itself and other extra relative to a feeder or filter. + +| Name | Description | +| --- | --- | +| source_feeder | the name of the feeder creates this Message | +| rule_name | the name of the rule that contains this filter | \ No newline at end of file diff --git a/docs/go.sum b/docs/go.sum new file mode 100644 index 0000000..36dfc21 --- /dev/null +++ b/docs/go.sum @@ -0,0 +1,10 @@ +github.com/bep/empty-hugo-module v1.0.0/go.mod h1:whohinbSjMoFi/Skivj9kvdPs1tEgzYpZ4rXoQk/0/I= +github.com/jquery/jquery-dist v0.0.0-20190501211928-15bc73803f76/go.mod h1:/lTfttEqFU0GWTaOOMIeNTzLGQ7yTIgyzjtkS/pYIoc= +github.com/jquery/jquery-dist v0.0.0-20200504225046-4c0e4becb826 h1:JO+IS20NQ+R4nFQT4doRfL3hE75WJK/+XZbpSlBW92Y= +github.com/jquery/jquery-dist v0.0.0-20200504225046-4c0e4becb826/go.mod h1:/lTfttEqFU0GWTaOOMIeNTzLGQ7yTIgyzjtkS/pYIoc= +github.com/olivernn/lunr.js v2.3.8+incompatible/go.mod h1:yEkQ1DUSMtNsn8n2CqvQXZd0ErWPEG8g9QRmblR+KS8= +github.com/olivernn/lunr.js v2.3.9+incompatible h1:eH8iBnjlR4mwlYDdNuqy9PCNLjp2bEs6aoNnTSaccx0= +github.com/olivernn/lunr.js v2.3.9+incompatible/go.mod h1:yEkQ1DUSMtNsn8n2CqvQXZd0ErWPEG8g9QRmblR+KS8= +github.com/slatedocs/slate v2.3.1+incompatible/go.mod h1:n698aXLkExWIlF7prJey0Kq6wlKIKvj/stVb5oouZDM= +github.com/slatedocs/slate v2.7.1+incompatible h1:U0wXBtrCSJq8PAePS4Gxf6yLdXsYRMXEHpaZ6Is4fTg= +github.com/slatedocs/slate v2.7.1+incompatible/go.mod h1:n698aXLkExWIlF7prJey0Kq6wlKIKvj/stVb5oouZDM= diff --git a/docs/resources/_gen/assets/scss/driplane/sass/main.scss_b4f67ac5085b89b62b54c1923e5a9145.content b/docs/resources/_gen/assets/scss/driplane/sass/main.scss_b4f67ac5085b89b62b54c1923e5a9145.content new file mode 100644 index 0000000..0f2eac0 --- /dev/null +++ b/docs/resources/_gen/assets/scss/driplane/sass/main.scss_b4f67ac5085b89b62b54c1923e5a9145.content @@ -0,0 +1 @@ +.theme__light .chroma{background-color:#f5f2f0}.theme__light .chroma .err{color:#a61717;background-color:#e3d2d2}.theme__light .chroma .lntd{vertical-align:top;padding:0;margin:0;border:0}.theme__light .chroma .lntable{border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block}.theme__light .chroma .hl{display:block;width:100%;background-color:#ffc}.theme__light .chroma .lnt{padding:0 .4em;color:#728fcb}.theme__light .chroma .ln{padding:0 .4em;color:#728fcb}.theme__light .chroma .k{color:#728fcb;font-weight:700}.theme__light .chroma .kc{color:#728fcb;font-weight:700}.theme__light .chroma .kd{color:#728fcb;font-weight:700}.theme__light .chroma .kn{color:#728fcb;font-weight:700}.theme__light .chroma .kp{color:#728fcb;font-weight:700}.theme__light .chroma .kr{color:#728fcb;font-weight:700}.theme__light .chroma .kt{color:#458;font-weight:700}.theme__light .chroma .na{color:#896724}.theme__light .chroma .nb{color:#0086b3}.theme__light .chroma .bp{color:#b6ad9a}.theme__light .chroma .nc{color:#458;font-weight:700}.theme__light .chroma .no{color:#896724}.theme__light .chroma .nd{color:#3c5d5d;font-weight:700}.theme__light .chroma .ni{color:#728fcb}.theme__light .chroma .ne{color:#b29762;font-weight:700}.theme__light .chroma .nf{color:#b29762;font-weight:700}.theme__light .chroma .nl{color:#b29762;font-weight:700}.theme__light .chroma .nn{color:#555}.theme__light .chroma .nt{color:#063289}.theme__light .chroma .nv{color:#896724}.theme__light .chroma .vc{color:#896724}.theme__light .chroma .vg{color:#896724}.theme__light .chroma .vi{color:#896724}.theme__light .chroma .s{color:#728fcb}.theme__light .chroma .sa{color:#728fcb}.theme__light .chroma .sb{color:#728fcb}.theme__light .chroma .sc{color:#728fcb}.theme__light .chroma .dl{color:#728fcb}.theme__light .chroma .sd{color:#728fcb}.theme__light .chroma .s2{color:#728fcb}.theme__light .chroma .se{color:#728fcb}.theme__light .chroma .sh{color:#728fcb}.theme__light .chroma .si{color:#728fcb}.theme__light .chroma .sx{color:#728fcb}.theme__light .chroma .sr{color:#009926}.theme__light .chroma .s1{color:#728fcb}.theme__light .chroma .ss{color:#990073}.theme__light .chroma .m{color:#099}.theme__light .chroma .mb{color:#099}.theme__light .chroma .mf{color:#099}.theme__light .chroma .mh{color:#099}.theme__light .chroma .mi{color:#099}.theme__light .chroma .il{color:#099}.theme__light .chroma .mo{color:#099}.theme__light .chroma .o{color:#728fcb;font-weight:700}.theme__light .chroma .ow{color:#728fcb;font-weight:700}.theme__light .chroma .c{color:#b6ad9a;font-style:italic}.theme__light .chroma .ch{color:#b6ad9a;font-style:italic}.theme__light .chroma .cm{color:#b6ad9a;font-style:italic}.theme__light .chroma .c1{color:#b6ad9a;font-style:italic}.theme__light .chroma .cs{color:#b6ad9a;font-weight:700;font-style:italic}.theme__light .chroma .cp{color:#b6ad9a;font-weight:700;font-style:italic}.theme__light .chroma .cpf{color:#b6ad9a;font-weight:700;font-style:italic}.theme__light .chroma .gd{color:#728fcb;background-color:#fdd}.theme__light .chroma .ge{color:#728fcb;font-style:italic}.theme__light .chroma .gr{color:#a00}.theme__light .chroma .gh{color:#b6ad9a}.theme__light .chroma .gi{color:#728fcb;background-color:#dfd}.theme__light .chroma .go{color:#888}.theme__light .chroma .gp{color:#555}.theme__light .chroma .gs{font-weight:700}.theme__light .chroma .gu{color:#aaa}.theme__light .chroma .gt{color:#a00}.theme__light .chroma .gl{text-decoration:underline}.theme__light .chroma .w{color:#bbb}.theme__light .chroma .p{color:#b6ad9a}.theme__dark .chroma{color:#f8f8f2;background-color:#282a36}.theme__dark .chroma .lntd{vertical-align:top;padding:0;margin:0;border:0}.theme__dark .chroma .lntable{border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block}.theme__dark .chroma .hl{display:block;width:100%;background-color:#000}.theme__dark .chroma .lnt{padding:0 .4em;color:#7f7f7f}.theme__dark .chroma .ln{padding:0 .4em;color:#7f7f7f}.theme__dark .chroma .k{color:#ff79c6}.theme__dark .chroma .kc{color:#ff79c6}.theme__dark .chroma .kd{color:#8be9fd;font-style:italic}.theme__dark .chroma .kn{color:#ff79c6}.theme__dark .chroma .kp{color:#ff79c6}.theme__dark .chroma .kr{color:#ff79c6}.theme__dark .chroma .kt{color:#8be9fd}.theme__dark .chroma .na{color:#50fa7b}.theme__dark .chroma .nb{color:#8be9fd;font-style:italic}.theme__dark .chroma .nc{color:#50fa7b}.theme__dark .chroma .nf{color:#50fa7b}.theme__dark .chroma .nl{color:#8be9fd;font-style:italic}.theme__dark .chroma .nt{color:#ff79c6}.theme__dark .chroma .nv{color:#8be9fd;font-style:italic}.theme__dark .chroma .vc{color:#8be9fd;font-style:italic}.theme__dark .chroma .vg{color:#8be9fd;font-style:italic}.theme__dark .chroma .vi{color:#8be9fd;font-style:italic}.theme__dark .chroma .s{color:#f1fa8c}.theme__dark .chroma .sa{color:#f1fa8c}.theme__dark .chroma .sb{color:#f1fa8c}.theme__dark .chroma .sc{color:#f1fa8c}.theme__dark .chroma .dl{color:#f1fa8c}.theme__dark .chroma .sd{color:#f1fa8c}.theme__dark .chroma .s2{color:#f1fa8c}.theme__dark .chroma .se{color:#f1fa8c}.theme__dark .chroma .sh{color:#f1fa8c}.theme__dark .chroma .si{color:#f1fa8c}.theme__dark .chroma .sx{color:#f1fa8c}.theme__dark .chroma .sr{color:#f1fa8c}.theme__dark .chroma .s1{color:#f1fa8c}.theme__dark .chroma .ss{color:#f1fa8c}.theme__dark .chroma .m{color:#bd93f9}.theme__dark .chroma .mb{color:#bd93f9}.theme__dark .chroma .mf{color:#bd93f9}.theme__dark .chroma .mh{color:#bd93f9}.theme__dark .chroma .mi{color:#bd93f9}.theme__dark .chroma .il{color:#bd93f9}.theme__dark .chroma .mo{color:#bd93f9}.theme__dark .chroma .o{color:#ff79c6}.theme__dark .chroma .ow{color:#ff79c6}.theme__dark .chroma .c{color:#6272a4}.theme__dark .chroma .ch{color:#6272a4}.theme__dark .chroma .cm{color:#6272a4}.theme__dark .chroma .c1{color:#6272a4}.theme__dark .chroma .cs{color:#6272a4}.theme__dark .chroma .cp{color:#ff79c6}.theme__dark .chroma .cpf{color:#ff79c6}.theme__dark .chroma .gd{color:#8b080b}.theme__dark .chroma .ge{text-decoration:underline}.theme__dark .chroma .gh{font-weight:700}.theme__dark .chroma .gi{font-weight:700}.theme__dark .chroma .go{color:#44475a}.theme__dark .chroma .gu{font-weight:700}.theme__dark .chroma .gl{text-decoration:underline}html{box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}.theme__dark a{text-decoration:none;color:#ffd866}.theme__dark a:hover,.theme__dark a:active,.theme__dark a:focus{color:#ff6188;text-decoration:underline}.theme__light a{text-decoration:none;color:#007d9c}.theme__light a:hover,.theme__light a:active,.theme__light a:focus{color:#00acd7;text-decoration:underline}/*!minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css*/html,body,p,ol,ul,li,dl,dt,dd,blockquote,figure,fieldset,legend,textarea,pre,iframe,hr,h1,h2,h3,h4,h5,h6{margin:0;padding:0}ul{list-style:none}hr{border:0}button,input,select,textarea{margin:0}img,video{height:auto;max-width:100%;object-fit:inherit}iframe{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}td:not([align]),th:not([align]){text-align:left}b,strong{font-weight:700}dfn{font-style:italic}figcaption{font-style:italic;font-size:.9rem;margin:.5rem 1rem 1rem}pre{white-space:pre;-webkit-hyphens:none;-ms-hyphens:none;hyphens:none}/*!Generated by Font Squirrel (https://www.fontsquirrel.com) on October 26, 2019*/@font-face{font-family:montserrat;src:url(../fonts/montserrat-regular.woff2)format("woff2"),url(../fonts/montserrat-regular.woff)format("woff");font-weight:400;font-style:normal;font-display:swap;unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:montserrat;src:url(../fonts/montserrat-bold.woff2)format("woff2"),url(../fonts/montserrat-bold.woff)format("woff");font-weight:700;font-style:normal;font-display:swap;unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:montserrat;src:url(../fonts/montserrat-black.woff2)format("woff2"),url(../fonts/montserrat-black.woff)format("woff");font-weight:900;font-style:normal;font-display:swap;unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:muli;font-style:normal;font-display:swap;font-weight:200;src:local("Muli Extra Light "),local("Muli-Extra Light"),url(../fonts/muli-latin-200.woff2)format("woff2"),url(../fonts/muli-latin-200.woff)format("woff")}@font-face{font-family:muli;font-style:italic;font-display:swap;font-weight:200;src:local("Muli Extra Light italic"),local("Muli-Extra Lightitalic"),url(../fonts/muli-latin-200italic.woff2)format("woff2"),url(../fonts/muli-latin-200italic.woff)format("woff")}@font-face{font-family:muli;font-style:normal;font-display:swap;font-weight:300;src:local("Muli Light "),local("Muli-Light"),url(../fonts/muli-latin-300.woff2)format("woff2"),url(../fonts/muli-latin-300.woff)format("woff")}@font-face{font-family:muli;font-style:italic;font-display:swap;font-weight:300;src:local("Muli Light italic"),local("Muli-Lightitalic"),url(../fonts/muli-latin-300italic.woff2)format("woff2"),url(../fonts/muli-latin-300italic.woff)format("woff")}@font-face{font-family:muli;font-style:normal;font-display:swap;font-weight:400;src:local("Muli Regular "),local("Muli-Regular"),url(../fonts/muli-latin-400.woff2)format("woff2"),url(../fonts/muli-latin-400.woff)format("woff")}@font-face{font-family:muli;font-style:italic;font-display:swap;font-weight:400;src:local("Muli Regular italic"),local("Muli-Regularitalic"),url(../fonts/muli-latin-400italic.woff2)format("woff2"),url(../fonts/muli-latin-400italic.woff)format("woff")}@font-face{font-family:muli;font-style:normal;font-display:swap;font-weight:600;src:local("Muli SemiBold "),local("Muli-SemiBold"),url(../fonts/muli-latin-600.woff2)format("woff2"),url(../fonts/muli-latin-600.woff)format("woff")}@font-face{font-family:muli;font-style:italic;font-display:swap;font-weight:600;src:local("Muli SemiBold italic"),local("Muli-SemiBolditalic"),url(../fonts/muli-latin-600italic.woff2)format("woff2"),url(../fonts/muli-latin-600italic.woff)format("woff")}@font-face{font-family:muli;font-style:normal;font-display:swap;font-weight:700;src:local("Muli Bold "),local("Muli-Bold"),url(../fonts/muli-latin-700.woff2)format("woff2"),url(../fonts/muli-latin-700.woff)format("woff")}@font-face{font-family:muli;font-style:italic;font-display:swap;font-weight:700;src:local("Muli Bold italic"),local("Muli-Bolditalic"),url(../fonts/muli-latin-700italic.woff2)format("woff2"),url(../fonts/muli-latin-700italic.woff)format("woff")}@font-face{font-family:muli;font-style:normal;font-display:swap;font-weight:800;src:local("Muli ExtraBold "),local("Muli-ExtraBold"),url(../fonts/muli-latin-800.woff2)format("woff2"),url(../fonts/muli-latin-800.woff)format("woff")}@font-face{font-family:muli;font-style:italic;font-display:swap;font-weight:800;src:local("Muli ExtraBold italic"),local("Muli-ExtraBolditalic"),url(../fonts/muli-latin-800italic.woff2)format("woff2"),url(../fonts/muli-latin-800italic.woff)format("woff")}@font-face{font-family:muli;font-style:normal;font-display:swap;font-weight:900;src:local("Muli Black "),local("Muli-Black"),url(../fonts/muli-latin-900.woff2)format("woff2"),url(../fonts/muli-latin-900.woff)format("woff")}@font-face{font-family:muli;font-style:italic;font-display:swap;font-weight:900;src:local("Muli Black italic"),local("Muli-Blackitalic"),url(../fonts/muli-latin-900italic.woff2)format("woff2"),url(../fonts/muli-latin-900italic.woff)format("woff")}.clearfix::after{clear:both;content:'';display:table}.capitalize{text-transform:capitalize}.hide{display:none}.grow{-webkit-flex-grow:1;-moz-flex-grow:1;-ms-flex-grow:1;flex-grow:1}.flexbox{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}.flexcolumn{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.jc-center{-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center}.ai-center{-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center}.flex-wrap{-webkit-flex-wrap:wrap;-moz-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{font-size:1rem;font-family:muli,avenir,helvetica neue,helvetica,ubuntu,roboto,noto,segoe ui,arial,sans-serif}code,pre{font-size:.85rem;font-family:Consolas,Monaco,Menlo,dejavu sans mono,bitstream vera sans mono,courier new,lucida console,lucida sans typewriter,liberation mono,nimbus mono l,Monaco,Courier,monospace}.h1{font-size:4rem}.h2{font-size:3.5rem}.h3{font-size:3rem}.h4{font-size:2.5rem}.h5{font-size:2rem}.h6{font-size:1.5rem}.p1{font-size:1.2rem}.p2{font-size:1rem}.caption{font-size:.8rem}@-webkit-keyframes slide-in-down{0%{transform:translate(0,-12%);opacity:0}100%{transform:translate(0,0);opacity:1}}@-moz-keyframes slide-in-down{0%{transform:translate(0,-12%);opacity:0}100%{transform:translate(0,0);opacity:1}}@-ms-keyframes slide-in-down{0%{transform:translate(0,-12%);opacity:0}100%{transform:translate(0,0);opacity:1}}@-o-keyframes slide-in-down{0%{transform:translate(0,-12%);opacity:0}100%{transform:translate(0,0);opacity:1}}@keyframes slide-in-down{0%{transform:translate(0,-12%);opacity:0}100%{transform:translate(0,0);opacity:1}}@-webkit-keyframes slide-in-left{0%{transform:translate(-12%,0);opacity:0}100%{transform:translate(0,0);opacity:1}}@-moz-keyframes slide-in-left{0%{transform:translate(-12%,0);opacity:0}100%{transform:translate(0,0);opacity:1}}@-ms-keyframes slide-in-left{0%{transform:translate(-12%,0);opacity:0}100%{transform:translate(0,0);opacity:1}}@-o-keyframes slide-in-left{0%{transform:translate(-12%,0);opacity:0}100%{transform:translate(0,0);opacity:1}}@keyframes slide-in-left{0%{transform:translate(-12%,0);opacity:0}100%{transform:translate(0,0);opacity:1}}.menu{position:-webkit-sticky;position:sticky;top:50px;padding:.5rem;margin:.5rem;margin-top:0;padding-top:.85rem;height:calc(100vh - $grid-nav-height);overflow-y:auto;z-index:9}@media only screen and (max-width:600px){.menu{top:0}}.menu__label{font-family:montserrat,sans-serif;font-size:1rem;margin:.65rem 0;padding-bottom:.5rem;text-transform:capitalize}@media only screen and (max-width:600px){.menu__label{text-align:center;font-size:1.125rem}}.menu__title{cursor:pointer;position:relative;word-break:break-word;font-size:.925rem;height:30px;margin:.25rem 0;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center}.menu__title[data-depth="1"]{font-size:.925rem;margin-left:1.25rem}.menu__title[data-depth="2"]{font-size:.925rem;margin-left:2.5rem}.menu__title[data-depth="3"]{font-size:.925rem;margin-left:3.75rem}.menu__title[data-depth="4"]{font-size:.925rem;margin-left:5rem}.theme__dark .menu__title{color:#fcfcfa}.theme__dark .menu__title.active{font-weight:700;color:#aed581}.theme__light .menu__title{color:#242729}.theme__light .menu__title.active{font-weight:700;color:#007d9c}.menu__title--collapse{cursor:pointer;word-break:break-word;font-size:16px;height:30px;margin:.25rem 0;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center}.menu__title--collapse[data-depth="1"]{font-size:.925rem;margin-left:1.25rem}.menu__title--collapse[data-depth="2"]{font-size:.925rem;margin-left:2.5rem}.menu__title--collapse[data-depth="3"]{font-size:.925rem;margin-left:3.75rem}.menu__title--collapse[data-depth="4"]{font-size:.925rem;margin-left:5rem}.theme__dark .menu__title--collapse{color:#fcfcfa}.theme__dark .menu__title--collapse.active svg{color:#aed581}.theme__light .menu__title--collapse{color:#242729}.theme__light .menu__title--collapse.active svg{color:#007d9c}.theme__dark .menu__title--collapse:hover,.theme__dark .menu__title--collapse:active,.theme__dark .menu__title--collapse:focus{color:#ff6188}.theme__dark .menu__title--collapse:hover svg,.theme__dark .menu__title--collapse:active svg,.theme__dark .menu__title--collapse:focus svg{color:#ff6188;-webkit-transform:translateX(.125rem);-moz-transform:translateX(.125rem);-ms-transform:translateX(.125rem);transform:translateX(.125rem)}.theme__light .menu__title--collapse:hover,.theme__light .menu__title--collapse:active,.theme__light .menu__title--collapse:focus{color:#00acd7}.theme__light .menu__title--collapse:hover svg,.theme__light .menu__title--collapse:active svg,.theme__light .menu__title--collapse:focus svg{color:#00acd7;-webkit-transform:translateX(.125rem);-moz-transform:translateX(.125rem);-ms-transform:translateX(.125rem);transform:translateX(.125rem)}.menu__title--icon{margin-top:2px}.theme__dark .menu__title--icon{color:#fcfcfa}.theme__light .menu__title--icon{color:#535a61}.menu__title--icon.down{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg);-webkit-transition:all .15s ease;-moz-transition:all .15s ease;-ms-transition:all .15s ease;-o-transition:all .15s ease;transition:all .15s ease}.menu__title--icon.downrtl{-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg);-webkit-transition:all .15s ease;-moz-transition:all .15s ease;-ms-transition:all .15s ease;-o-transition:all .15s ease;transition:all .15s ease}.menu__title--icon.right{-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-ms-transform:rotate(0deg);transform:rotate(0deg);-webkit-transition:all .15s ease;-moz-transition:all .15s ease;-ms-transition:all .15s ease;-o-transition:all .15s ease;transition:all .15s ease}.menu__title--icon svg{display:block;margin:auto 0;-webkit-transition:all .15s ease;-moz-transition:all .15s ease;-ms-transition:all .15s ease;-o-transition:all .15s ease;transition:all .15s ease}.menu__alone{cursor:pointer;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.menu__list{max-height:0;overflow:hidden;word-wrap:break-word;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-ms-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.menu__list li{margin-left:1.25rem}.menu__list li.active{font-weight:700}.menu .active{max-height:100%}.theme__dark .menu li.active a{font-weight:700}.theme__light .menu li.active a{font-weight:700}.toc{position:-webkit-sticky;position:sticky;top:50px;padding:.5rem;margin:.5rem;margin-top:0;padding-top:1.25rem;height:calc(100vh - $grid-nav-height);overflow-y:auto;font-size:.85rem;z-index:4;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.toc #TableOfContents{position:relative}.toc__label{font-family:montserrat,sans-serif;font-size:1rem;margin-top:.65rem;margin-bottom:1rem;margin-left:1.25rem;padding-bottom:.5rem}.theme__dark .toc a{color:#aaa;position:relative}.theme__dark .toc a:hover,.theme__dark .toc a:active,.theme__dark .toc a:focus{color:#ff6188}.theme__dark .toc a.active{color:#aed581}.theme__dark .toc a.active::before{background-color:#aed581;content:'';height:11px;left:-8px;margin:.25rem 0;position:absolute;width:2px}.theme__dark .toc a.active::before:last-child{background-color:transparent}.theme__light .toc a{color:#919191;position:relative}.theme__light .toc a:hover,.theme__light .toc a:active,.theme__light .toc a:focus{color:#00acd7}.theme__light .toc a.active{color:#007d9c}.theme__light .toc a.active::before{background-color:#007d9c;content:'';height:11px;left:-8px;margin:.25rem 0;position:absolute;width:2px}.theme__light .toc a.active::before:last-child{background-color:transparent}.toc ul li li{margin-left:.85rem}.expand__content #TableOfContents ul{list-style-type:circle}.search{height:30px;width:240px;position:relative;border-radius:.175rem;z-index:10;margin:0 .75rem;-webkit-box-shadow:0 0 0 3px transparent;-moz-box-shadow:0 0 0 3px transparent;box-shadow:0 0 0 3px transparent;-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;-ms-transition:all .2s ease-in;-o-transition:all .2s ease-in;transition:all .2s ease-in;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;-webkit-transition:all .15s ease;-moz-transition:all .15s ease;-ms-transition:all .15s ease;-o-transition:all .15s ease;transition:all .15s ease}.theme__dark .search[data-bgimg=true]{border:2px solid transparent;background-color:transparent}.theme__dark .search[data-bgimg=true]:focus-within{background-color:#4d4a4e;border:2px solid #424242;-webkit-box-shadow:0 0 0 3px rgba(166,166,166,.45);-moz-box-shadow:0 0 0 3px rgba(166,166,166,.45);box-shadow:0 0 0 3px rgba(166,166,166,.45)}.theme__light .search[data-bgimg=true]{border:2px solid transparent;background-color:transparent}.theme__light .search[data-bgimg=true]:focus-within{background-color:#fff;border:2px solid #b0bec5;-webkit-box-shadow:0 0 0 3px rgba(207,216,220,.6);-moz-box-shadow:0 0 0 3px rgba(207,216,220,.6);box-shadow:0 0 0 3px rgba(207,216,220,.6)}.theme__dark .search[data-bgimg=false]{border:2px solid #383838;background-color:#4d4a4e}.theme__dark .search[data-bgimg=false]:focus-within{border:2px solid #424242;-webkit-box-shadow:0 0 0 3px rgba(166,166,166,.45);-moz-box-shadow:0 0 0 3px rgba(166,166,166,.45);box-shadow:0 0 0 3px rgba(166,166,166,.45)}.theme__light .search[data-bgimg=false]{border:2px solid #e0e0e0;background-color:#fff}.theme__light .search[data-bgimg=false]:focus-within{border:2px solid #b0bec5;-webkit-box-shadow:0 0 0 3px rgba(207,216,220,.6);-moz-box-shadow:0 0 0 3px rgba(207,216,220,.6);box-shadow:0 0 0 3px rgba(207,216,220,.6)}@media only screen and (max-width:1280px){.search{width:170px}}@media only screen and (max-width:960px){.search{display:none}}.search .icon{padding:.45rem;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}.theme__dark .search .icon{color:#999}.theme__light .search .icon{color:#aaa}.search .input{width:100%;font-size:.9rem;border:none;outline:none;padding-right:1rem}.theme__dark .search .input{color:#fcfcfa;background-color:inherit}.theme__dark .search .input.placeholder{color:#999}.theme__dark .search .input:-moz-placeholder{color:#999}.theme__dark .search .input::-moz-placeholder{color:#999}.theme__dark .search .input:-ms-input-placeholder{color:#999}.theme__dark .search .input::-webkit-input-placeholder{color:#999}.theme__light .search .input{color:#242729;background-color:inherit}.theme__light .search .input.placeholder{color:#aaa}.theme__light .search .input:-moz-placeholder{color:#aaa}.theme__light .search .input::-moz-placeholder{color:#aaa}.theme__light .search .input:-ms-input-placeholder{color:#aaa}.theme__light .search .input::-webkit-input-placeholder{color:#aaa}.search-content{margin-top:.25rem;max-height:350px;width:325px;overflow:auto}.search-content a{text-decoration:none!important}.theme__dark .search__highlight{color:#ff6188}.theme__light .search__highlight{color:#ff6188}.search-result{position:absolute;width:100%;height:calc(100% - 8px);z-index:16;margin:4px 0}.theme__dark .search-result{background-color:#2d2a2e}.theme__light .search-result{background-color:#fff}.search-result[data-display=block]{display:block}.search-result[data-display=none]{display:none}.search-result__close{position:absolute;right:.25rem;top:.25rem;cursor:pointer}.theme__dark .search-result__close{color:#fcfcfa}.theme__dark .search-result__close:hover,.theme__dark .search-result__close:active,.theme__dark .search-result__close:focus{color:#aed581}.theme__light .search-result__close{color:#242729}.theme__light .search-result__close:hover,.theme__light .search-result__close:active,.theme__light .search-result__close:focus{color:#007d9c}.search-result__body{margin-top:2.25rem;padding:0 1rem;position:relative;display:block;overflow:auto;height:calc(100% - 3rem)}.theme__dark .search-result__body{scrollbar-width:thin;scrollbar-color:#888 #eee}.theme__dark .search-result__body::-webkit-scrollbar{width:.45em;height:.45em}.theme__dark .search-result__body::-webkit-scrollbar-thumb{background:#888}.theme__dark .search-result__body::-webkit-scrollbar-track{background:#eee}.theme__light .search-result__body{scrollbar-width:thin;scrollbar-color:#cfd8dc #fcfcfa}.theme__light .search-result__body::-webkit-scrollbar{width:.45em;height:.45em}.theme__light .search-result__body::-webkit-scrollbar-thumb{background:#cfd8dc}.theme__light .search-result__body::-webkit-scrollbar-track{background:#fcfcfa}.search-result__item{padding:1rem 0}.theme__dark .search-result__item{border-bottom:2px dashed #595b5c}.theme__dark .search-result__item--title{font-family:montserrat,sans-serif;font-size:1rem;margin:.25rem 0;color:#fcfcfa}.theme__dark .search-result__item--title::before{content:"📋 "}.theme__dark .search-result__item--desc{font-size:.9rem;margin:.25rem 0;color:#fcfcfa}.theme__light .search-result__item{border-bottom:2px dashed #bdbdbd}.theme__light .search-result__item--title{font-family:montserrat,sans-serif;font-size:1rem;margin:.25rem 0;color:#424242}.theme__light .search-result__item--title::before{content:"📋 "}.theme__light .search-result__item--desc{font-size:.9rem;margin:.25rem 0;color:#242729}.menu-item{padding:.25rem}.menu-item__title{font-size:1rem}.theme__dark .menu-item__title{color:#fcfcfa}.theme__light .menu-item__title{color:#242729}.menu-item__desc{font-size:.8rem;padding:.25rem .5rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:325px}#search-results.dd{display:none;z-index:16}#search-results.dd.is-active{display:inline-block;position:absolute;top:40px;right:0;width:325px;border-radius:.175rem;-webkit-box-shadow:0 1px 3px 0 rgba(0,0,0,.4);-moz-box-shadow:0 1px 3px 0 rgba(0,0,0,.4);box-shadow:0 1px 3px 0 rgba(0,0,0,.4)}.theme__dark #search-results.dd.is-active{background-color:#212121}.theme__light #search-results.dd.is-active{background-color:#f7f8f9}#search-results .dd-content{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.theme__dark #search-results .dd-content{background-color:#4d4a4e;scrollbar-width:thin;scrollbar-color:#888 #eee}.theme__dark #search-results .dd-content::-webkit-scrollbar{width:.45em;height:.45em}.theme__dark #search-results .dd-content::-webkit-scrollbar-thumb{background:#888}.theme__dark #search-results .dd-content::-webkit-scrollbar-track{background:#eee}.theme__light #search-results .dd-content{background-color:#f1f1f1;scrollbar-width:thin;scrollbar-color:#cfd8dc #fcfcfa}.theme__light #search-results .dd-content::-webkit-scrollbar{width:.45em;height:.45em}.theme__light #search-results .dd-content::-webkit-scrollbar-thumb{background:#cfd8dc}.theme__light #search-results .dd-content::-webkit-scrollbar-track{background:#fcfcfa}#search-results .dd-item{width:100%;font-size:1rem;padding:.35rem .6rem}#search-results .dd-item:hover,#search-results .dd-item:active,#search-results .dd-item:focus{border-bottom-left-radius:.1rem;border-bottom-right-radius:.1rem}.theme__dark #search-results .dd-item:hover,.theme__dark #search-results .dd-item:active,.theme__dark #search-results .dd-item:focus{background-color:#403e41}.theme__light #search-results .dd-item:hover,.theme__light #search-results .dd-item:active,.theme__light #search-results .dd-item:focus{background-color:#eaeaea}.theme__dark #search-results .dd-item.is-active{background-color:#403e41}.theme__light #search-results .dd-item.is-active{background-color:#eaeaea}.mobile-search{position:absolute;left:0;top:0;width:100%;z-index:18;overflow:hidden}.theme__dark .mobile-search ::-webkit-scrollbar{width:.45em;height:.45em}.theme__dark .mobile-search ::-webkit-scrollbar-thumb{background:#888}.theme__dark .mobile-search ::-webkit-scrollbar-track{background:#eee}.theme__light .mobile-search ::-webkit-scrollbar{width:.45em;height:.45em}.theme__light .mobile-search ::-webkit-scrollbar-thumb{background:#cfd8dc}.theme__light .mobile-search ::-webkit-scrollbar-track{background:#fcfcfa}.mobile-search__top{width:100%;text-align:right;position:relative;height:50px;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center}.theme__dark .mobile-search__top{background-color:#403e41}.theme__light .mobile-search__top{background-color:#fafafa}.mobile-search__top--icon{width:50px;cursor:pointer;position:absolute;right:0;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center}.theme__dark .mobile-search__top--icon:hover,.theme__dark .mobile-search__top--icon:active,.theme__dark .mobile-search__top--icon:focus{color:#aed581}.theme__light .mobile-search__top--icon:hover,.theme__light .mobile-search__top--icon:active,.theme__light .mobile-search__top--icon:focus{color:#007d9c}.mobile-search__top--input{width:calc(100% - 70px);height:70%;outline:none;border:none;border-radius:.25rem;padding:0 1rem;font-size:1.1rem}.theme__dark .mobile-search__top--input{color:#fcfcfa;background-color:#403e41}.theme__dark .mobile-search__top--input.placeholder{color:#999}.theme__dark .mobile-search__top--input:-moz-placeholder{color:#999}.theme__dark .mobile-search__top--input::-moz-placeholder{color:#999}.theme__dark .mobile-search__top--input:-ms-input-placeholder{color:#999}.theme__dark .mobile-search__top--input::-webkit-input-placeholder{color:#999}.theme__light .mobile-search__top--input{color:#242729;background-color:#fafafa}.theme__light .mobile-search__top--input.placeholder{color:#aaa}.theme__light .mobile-search__top--input:-moz-placeholder{color:#aaa}.theme__light .mobile-search__top--input::-moz-placeholder{color:#aaa}.theme__light .mobile-search__top--input:-ms-input-placeholder{color:#aaa}.theme__light .mobile-search__top--input::-webkit-input-placeholder{color:#aaa}.mobile-search__body{width:100%;height:calc(100vh - $grid-nav-height);overflow:auto}.theme__dark .mobile-search__body{color:#fcfcfa;background-color:#2d2a2e;scrollbar-width:thin;scrollbar-color:#888 #eee}.theme__light .mobile-search__body{color:#242729;background-color:#fff;scrollbar-width:thin;scrollbar-color:#cfd8dc #fcfcfa}.mobile-search__btn{width:100%;z-index:11;background-color:transparent;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center}.theme__dark .mobile-search__btn:hover,.theme__dark .mobile-search__btn:active,.theme__dark .mobile-search__btn:focus{color:#aed581}.theme__light .mobile-search__btn:hover,.theme__light .mobile-search__btn:active,.theme__light .mobile-search__btn:focus{color:#007d9c}.theme__dark .mobile-search__content{background-color:#4d4a4e}.theme__light .mobile-search__content{background-color:#f1f1f1}.mobile-search__content a{text-decoration:none!important}.mobile-search__item{padding:.5rem;list-style-type:none}.mobile-search__item--title{font-size:1.2rem}.theme__dark .mobile-search__item--title{color:#fcfcfa}.theme__light .mobile-search__item--title{color:#242729}.mobile-search__item--title::before{content:"📋 "}.mobile-search__item--desc{font-size:.9rem;padding:.25rem .5rem}.theme__dark .mobile-search__item:hover,.theme__dark .mobile-search__item:active,.theme__dark .mobile-search__item:focus{background-color:#403e41}.theme__light .mobile-search__item:hover,.theme__light .mobile-search__item:active,.theme__light .mobile-search__item:focus{background-color:#eaeaea}.dropdown{position:relative;display:inline-block;height:100%}.dropdown-content{display:none;position:absolute;z-index:17}.dropdown-content a{padding:.3rem .5rem;text-decoration:none;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:120px}.dropdown:hover .dropdown-content{display:block}.drawer{position:fixed;top:0;left:-100%;z-index:19;width:240px;height:100%;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-ms-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.theme__dark .drawer{background-color:#2d2a2e}.theme__light .drawer{background-color:#fff}.drawer__header{height:50px;width:100%;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}.theme__dark .drawer__header{background-color:#403e41;box-shadow:0 1px 0 rgba(12,13,14,.1),0 1px 6px rgba(60,65,70,.1)}.theme__light .drawer__header{background-color:#fafafa;box-shadow:0 1px 0 rgba(12,13,14,.1),0 1px 6px rgba(60,65,70,.1)}.drawer__header--text{width:100%;height:100%;padding:1rem;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:flex-start;-moz-justify-content:flex-start;-ms-justify-content:flex-start;justify-content:flex-start;-ms-flex-pack:flex-start}.theme__dark .drawer__header--text{color:#fcfcfa}.theme__light .drawer__header--text{color:#424242}.drawer__body{height:100%;width:100%;overflow-y:auto}.drawer__close{width:50px;height:100%;cursor:pointer;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center}.theme__dark .drawer__close{color:#fcfcfa}.theme__dark .drawer__close:hover,.theme__dark .drawer__close:active,.theme__dark .drawer__close:focus{color:#aed581}.theme__light .drawer__close{color:#242729}.theme__light .drawer__close:hover,.theme__light .drawer__close:active,.theme__light .drawer__close:focus{color:#007d9c}.modal{position:fixed;z-index:18;left:-100%;top:0;right:0;bottom:0;width:100%;height:100%;overflow:hidden;opacity:0;background:rgba(0,0,0,.6);-webkit-transition:opacity .25s ease-in-out;-moz-transition:opacity .25s ease-in-out;-ms-transition:opacity .25s ease-in-out;-o-transition:opacity .25s ease-in-out;transition:opacity .25s ease-in-out}.lang{width:100%;font-size:17.2px;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-justify-content:space-between;-moz-justify-content:space-between;-ms-justify-content:space-between;justify-content:space-between;-ms-flex-pack:space-between;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center}.lang__dropdown{outline:none;cursor:pointer;border:none;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center}.lang__dropdown--content{padding:.25rem 0;max-width:120px;border-radius:.175rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:120px;-webkit-box-shadow:0 1px 3px 0 rgba(0,0,0,.4);-moz-box-shadow:0 1px 3px 0 rgba(0,0,0,.4);box-shadow:0 1px 3px 0 rgba(0,0,0,.4)}.theme__dark .lang__dropdown--content{background-color:#595b5c}.theme__dark .lang__dropdown--content a{text-decoration:none;color:#fcfcfa}.theme__dark .lang__dropdown--content a:hover,.theme__dark .lang__dropdown--content a:active,.theme__dark .lang__dropdown--content a:focus{color:inherit;background-color:#727072}.theme__dark .lang__dropdown--content a.active{font-weight:700;color:#aed581;background-color:#424242}.theme__light .lang__dropdown--content{background-color:#fff}.theme__light .lang__dropdown--content a{text-decoration:none;color:#242729}.theme__light .lang__dropdown--content a:hover,.theme__light .lang__dropdown--content a:active,.theme__light .lang__dropdown--content a:focus{color:inherit;background-color:rgba(225,225,225,.4)}.theme__light .lang__dropdown--content a.active{font-weight:700;color:#007d9c;background-color:#e0e0e0}.lang__dropdown--item{padding:.25rem .75rem;width:100%;height:100%;text-decoration:none;display:block;font-size:1rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:120px}.breadcrumb[data-is-blog=true]{margin:1.5rem 1rem 0;padding-bottom:1.5rem}.theme__dark .breadcrumb[data-is-blog=true]{border-bottom:1px solid #595b5c;background-color:#2d2a2e}.theme__light .breadcrumb[data-is-blog=true]{border-bottom:1px solid #bdbdbd;background-color:#fff}.breadcrumb[data-is-blog=false]{margin:auto 1rem;padding:.5rem 0}.breadcrumb ol{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;-webkit-flex-wrap:wrap;-moz-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.breadcrumb li{display:inline;font-size:.9rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:300px}.theme__dark .breadcrumb li a:hover,.theme__dark .breadcrumb li a:active,.theme__dark .breadcrumb li a:focus{color:#ff6188}.theme__light .breadcrumb li a:hover,.theme__light .breadcrumb li a:active,.theme__light .breadcrumb li a:focus{color:#00acd7}.breadcrumb li+li:before{padding:.5rem;content:"»"}.pagination{border-radius:.25rem;margin:2rem 1rem;padding:.5rem 0;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center}.pagination li{border-radius:.25rem}.theme__dark .pagination li.disabled a:hover,.theme__dark .pagination li.disabled a:active,.theme__dark .pagination li.disabled a:focus{color:#fcfcfa;text-decoration:none}.theme__light .pagination li.disabled a:hover,.theme__light .pagination li.disabled a:active,.theme__light .pagination li.disabled a:focus{color:#757575;text-decoration:none}.pagination li.active{font-weight:700}.theme__dark .pagination li.active a{color:#ff6188;border-bottom:5px solid #fcfcfa}.theme__light .pagination li.active a{color:#00acd7;border-bottom:5px solid #757575}.pagination a{font-size:1.25rem;padding:.5rem .75rem}.theme__dark .pagination a{color:#fcfcfa}.theme__dark .pagination a:hover,.theme__dark .pagination a:active,.theme__dark .pagination a:focus{color:#ff6188}.theme__light .pagination a{color:#757575}.theme__light .pagination a:hover,.theme__light .pagination a:active,.theme__light .pagination a:focus{color:#00acd7}.pagination-single{margin:1rem 0;padding-top:.75rem;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center;-webkit-flex-wrap:wrap;-moz-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.pagination-single__left,.pagination-single__right{padding:.25rem;border-radius:.125rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:769px;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center}.theme__dark .pagination-single__left,.theme__dark .pagination-single__right{color:#fcfcfa}.theme__light .pagination-single__left,.theme__light .pagination-single__right{color:#535a61}.pagination-single__left-title,.pagination-single__right-title{font-size:16.8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:769px}.pagination-single__icon{border-radius:100%;margin:0 .5rem;color:inherit}.pagination-single__icon svg{display:block;margin:auto}.button{border:none;outline:none;padding:.75rem;border-radius:.25rem;text-decoration:none;cursor:pointer;-webkit-transition:all .15s ease-in;-moz-transition:all .15s ease-in;-ms-transition:all .15s ease-in;-o-transition:all .15s ease-in;transition:all .15s ease-in}.theme__dark .button[data-color=default]{color:#2d2a2e;border:1px solid #a6a6a6;background-color:#ccc}.theme__dark .button[data-color=default]:hover,.theme__dark .button[data-color=default]:active,.theme__dark .button[data-color=default]:focus{color:#2d2a2e;border:1px solid #a6a6a6;background-color:#e0e0e0}.theme__light .button[data-color=default]{color:#fff;border:1px solid #303438;background-color:#535a61}.theme__light .button[data-color=default]:hover,.theme__light .button[data-color=default]:active,.theme__light .button[data-color=default]:focus{color:#fff;border:1px solid #303438;background-color:#666e77}.theme__dark .button[data-color=primary]{color:#2d2a2e;border:1px solid #89c248;background-color:#aed581}.theme__dark .button[data-color=primary]:hover,.theme__dark .button[data-color=primary]:active,.theme__dark .button[data-color=primary]:focus{color:#2d2a2e;border:1px solid #89c248;background-color:#c2dfa0}.theme__light .button[data-color=primary]{color:#fff;border:1px solid #004050;background-color:#007d9c}.theme__light .button[data-color=primary]:hover,.theme__light .button[data-color=primary]:active,.theme__light .button[data-color=primary]:focus{color:#fff;border:1px solid #004050;background-color:#009ec5}.editBtn{border:none;outline:none;padding:.75rem;margin:0 .95rem;text-decoration:none;cursor:pointer;font-family:montserrat,sans-serif;background-color:transparent}.theme__dark .editBtn{color:#ccc}.theme__dark .editBtn:hover,.theme__dark .editBtn:active,.theme__dark .editBtn:focus{color:#fcfcfa;background-color:#727072}.theme__light .editBtn{color:#535a61}.theme__light .editBtn:hover,.theme__light .editBtn:active,.theme__light .editBtn:focus{color:#242729;background-color:rgba(225,225,225,.4)}@media only screen and (max-width:600px){.editBtn{display:none}}.summary-card{padding:1rem;padding-bottom:0;margin:1.5rem 0;position:relative}.theme__dark .summary-card{background-color:#2d2a2e;border-bottom:1px solid #595b5c}.theme__light .summary-card{background-color:#fff;border-bottom:1px solid #bdbdbd}.summary-card .title{text-align:center}.summary-card .title a{font-family:montserrat,sans-serif;font-weight:700;word-break:break-word}.theme__dark .summary-card .title a{color:#ffd866}.theme__dark .summary-card .title a:hover,.theme__dark .summary-card .title a:active,.theme__dark .summary-card .title a:focus{color:#ff6188}.theme__light .summary-card .title a{color:#007d9c}.theme__light .summary-card .title a:hover,.theme__light .summary-card .title a:active,.theme__light .summary-card .title a:focus{color:#00acd7}.summary-card .subtitle{padding:1rem 0;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center}.summary-card__links{font-size:.8rem;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;-moz-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.theme__dark .summary-card__links{background-color:#2d2a2e}.theme__light .summary-card__links{background-color:#fff}.summary-card__tag{margin-right:.5rem;margin-bottom:.35rem;padding:.125rem .25rem;border-top-left-radius:.15rem;border-top-right-radius:.15rem;cursor:pointer}.theme__dark .summary-card__tag{border:1px solid #595b5c;border-bottom:none}.theme__light .summary-card__tag{border:1px solid #bdbdbd;border-bottom:none}.summary-card__content{margin-bottom:1rem;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center}.summary-card__text{margin-top:1rem;line-height:1.7rem}.summary-card__image{width:100%;height:100%}.summary-card__image-wrapper{height:100%;width:auto;margin:0 auto;padding:1rem 0;padding-bottom:0}.summary-card__video{width:100%;max-height:500px;object-fit:contain}.summary-card__video-wrapper{padding:1rem;padding-bottom:0}.summary-card hr{margin-top:1.5rem}.theme__dark .summary-card hr{border-top:1px solid #595b5c}.theme__light .summary-card hr{border-top:1px solid #bdbdbd}.summary-card:not(:last-child) hr{margin-bottom:4rem}.summary-card:last-child hr{margin-bottom:2rem}.expand{position:relative;border-radius:.25rem}.expand__content{overflow:hidden;max-height:0;border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem;-webkit-transition:all .2s ease;-moz-transition:all .2s ease;-ms-transition:all .2s ease;-o-transition:all .2s ease;transition:all .2s ease}.expand__content li{font-size:15.2px;margin:0 0 .525rem 2rem!important}.expand__content li:first-child{margin-top:.25rem!important}.expand__content li li{font-size:14.4px;margin:0 0 .25rem 1.25rem!important}.expand__content--toc{font-family:montserrat,sans-serif;font-size:15.2px}.expand__content--toc li{list-style-type:'📂 '}.expand__content--toc li li{list-style-type:'📄 '}.expand__button{cursor:pointer;width:100%;padding:.5rem;text-align:left;outline:none;border:none;font-size:1rem;font-family:montserrat,sans-serif;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center}.theme__dark .expand__button{color:inherit;border-top:1px solid rgba(243,242,241,.1);background-color:#282529}.theme__dark .expand__button:hover,.theme__dark .expand__button:active,.theme__dark .expand__button:focus{background-color:#212121}.theme__light .expand__button{color:inherit;border-top:1px solid rgba(12,13,14,.1);background-color:#f7f8f9}.theme__light .expand__button:hover,.theme__light .expand__button:active,.theme__light .expand__button:focus{background-color:#eef0f2}.expand-label{cursor:pointer;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center}.expand-icon{padding-top:.125rem;padding-right:.5rem}.expand-icon__down{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg);-webkit-transition:all .15s ease;-moz-transition:all .15s ease;-ms-transition:all .15s ease;-o-transition:all .15s ease;transition:all .15s ease}.expand-icon__right{-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-ms-transform:rotate(0deg);transform:rotate(0deg);-webkit-transition:all .15s ease;-moz-transition:all .15s ease;-ms-transition:all .15s ease;-o-transition:all .15s ease;transition:all .15s ease}.theme__dark .bgcolor__header{background-color:#212121}.theme__dark .bgcolor__breadcrumb{background-color:#2d2a2e}.theme__light .bgcolor__header{background-color:#eee}.theme__light .bgcolor__breadcrumb{background-color:#fff}.tag{display:inline-block;margin:.25rem .4rem;text-decoration:none!important}.theme__dark .tag{color:#e9e9da}.theme__dark .tag:hover,.theme__dark .tag:active,.theme__dark .tag:focus{color:#ff6188}.theme__light .tag{color:#292929}.theme__light .tag:hover,.theme__light .tag:active,.theme__light .tag:focus{color:#00acd7}.tag__wrapper{padding:.3rem 0;margin:auto 0}.tag__text{font-size:.95rem;font-weight:700;color:inherit}.tag__num{font-size:.75rem;font-weight:700;color:inherit}.section__card{padding:1rem .75rem 2rem;position:relative}@media only screen and (max-width:960px){.section__card [data-mobile=false]{display:none}}@media only screen and (min-width:960px){.section__card [data-mobile=true]{display:none}}.section__card--header{position:relative;margin:2rem 0;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}.section__card--title{z-index:2;font-weight:700;font-family:montserrat,sans-serif}.section__card--subtitle{font-weight:700;font-family:montserrat,sans-serif;margin-bottom:1.5rem;text-align:center}.section__card--main{padding:.5rem 0;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}.section__card--item{width:33.33%;text-decoration:none;-webkit-flex-grow:1;-moz-flex-grow:1;-ms-flex-grow:1;flex-grow:1}.section__card--item:not(:first-child):not(:last-child){margin:0 1rem}.section__card--item:first-child{margin:0 1rem 0 0}.section__card--item:last-child{margin:0 0 0 1rem}.section__card--img{margin:auto;display:block}.section__card--img-wrapper{width:100%;margin-bottom:1rem}.section__card--content{margin-bottom:.75rem;font-size:1.125rem;word-wrap:break-word}@media only screen and (max-width:960px){.section__card--item{width:100%;margin:.5rem 0 2rem!important;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}.section__card--main{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-align-items:flex-start;-moz-align-items:flex-start;-ms-align-items:flex-start;-ms-flex-align:flex-start;align-items:flex-start}.section__card--subtitle{text-align:left}.section__card--img{display:inline-block;width:100%}.section__card--img-wrapper{min-width:112px;max-width:112px;margin-right:1rem}.section__card--content{margin-bottom:1.5rem}}.section__normal{position:relative;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}.section__normal--content{margin-bottom:.75rem;font-size:1.125rem;word-wrap:break-word}.section__normal--subtitle{font-weight:700;font-family:montserrat,sans-serif;margin:2rem 0}.section__normal--img{width:100%;min-width:100px;height:100%}.section__normal--img-wrapper{margin:auto 0;padding:0 1rem}.section__normal--img-wrapper[data-position=left]{margin-right:5rem}.section__normal--img-wrapper[data-position=right]{margin-left:5rem}@media only screen and (max-width:600px){.section__normal{-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.section__normal--img-wrapper[data-position=left]{margin:0 2rem}.section__normal--img-wrapper[data-position=right]{margin:0 2rem}}.section__highlight{z-index:1;position:absolute;left:0;bottom:-.25rem;width:100%;height:20px}.section__btn{width:100%;cursor:pointer;border:none;outline:none;border-radius:.25rem}.section__btn:hover,.section__btn:active,.section__btn:focus{border:1px solid #fff}.section__btn--micro{height:20px;font-size:14px;line-height:14px}.section__btn--mini{height:24px;font-size:15px;line-height:15px}.section__btn--small{height:28px;font-size:16px}.section__btn--medium{height:32px;font-size:17px;line-height:17px}.section__btn--large{height:36px;font-size:18px}.mermaid{width:100%;text-align:center;margin-bottom:1rem;overflow:auto}.switch{position:absolute;right:-2rem;top:1.75rem;display:inline-block;width:30px;height:16px;z-index:14}.switch input{opacity:0;width:0;height:0}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:transparent;-webkit-transition:.2s;transition:.2s}.slider:before{position:absolute;content:"";height:12px;width:13px;left:2px;bottom:2px;-webkit-transition:.2s;transition:.2s}.slider__icon{padding:.5rem}input:checked+.slider:before{-webkit-transform:translateX(13px);-ms-transform:translateX(13px);transform:translateX(13px)}.notices{position:relative;border-radius:.125rem;color:#fff;margin:2rem 0;padding:.3rem .5rem .3rem 2rem;font-size:.95rem}.notices a{text-decoration:underline}.notices>table{table-layout:fixed;width:100%;margin:10px 0;border-spacing:0}.notices.warning{border-top:30px solid #f1b37e;background:#fefaf5;color:rgba(150,90,38,.995)!important}.notices.warning::before{position:absolute;content:url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjMDAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjIxIiBoZWlnaHQ9IjIxIj48cGF0aCBmaWxsPSIjZmVmYWY1IiBkPSJNMTIgMy4wMjkyOTY5QzExLjQzNjgxMyAzLjAyOTI5NjkgMTAuODczODY5IDMuMjkxNzM5OSAxMC41NTg1OTQgMy44MTY0MDYyTDEuNzYxNzE4OCAxOC40NTExNzJDMS4xMTM0ODU0IDE5LjUyOTE4NiAxLjk0Mjg3IDIxIDMuMjAxMTcxOSAyMUgyMC43OTY4NzVDMjIuMDU0ODA1IDIxIDIyLjg4NjUxNSAxOS41MjkxODYgMjIuMjM4MjgxIDE4LjQ1MTE3MkwxMy40NDE0MDYgMy44MTY0MDYyQzEzLjEyNjEzMSAzLjI5MTc0IDEyLjU2MzE4NyAzLjAyOTI5NjkgMTIgMy4wMjkyOTY5em0wIDIuMjY5NTMxMkwyMC4yMzYzMjggMTlIMy43NjM2NzE5TDEyIDUuMjk4ODI4MXpNMTEgOXY1aDJWOUgxMXptMCA3djJoMlYxNkgxMXoiLz48L3N2Zz4=);top:-26.5px;left:.4rem;height:100%}.notices.warning::after{position:absolute;content:attr(data-title);font-family:montserrat,sans-serif;top:-26.5px;left:2rem;height:100%}.notices.warning a{font-weight:700;color:rgba(134,74,22,.995)}.theme__dark .notices.warning a:hover,.theme__dark .notices.warning a:active,.theme__dark .notices.warning a:focus{color:#ff6188}.theme__light .notices.warning a:hover,.theme__light .notices.warning a:active,.theme__light .notices.warning a:focus{color:#00acd7}.notices.warning>table thead{background:#f1b37e}.notices.warning>table th{color:rgba(134,74,22,.995)}.notices.warning>table th,.notices.warning>table td{padding:5px 15px;border:1px double rgba(166,106,54,.45)}.notices.warning p>code,.notices.warning li>code,.notices.warning td>code,.notices.warning code{padding:3px 7px;color:rgba(150,90,38,.995)!important;background-color:#fbecd9!important}.notices.error{border-top:30px solid #d58181;background:#fbeded;color:rgba(132,56,56,.995)!important}.notices.error::before{position:absolute;content:url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjMDAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjIxIiBoZWlnaHQ9IjIxIj48cGF0aCBmaWxsPSIjZmJlZGVkIiBkPSJNNSAzQzMuODk1IDMgMyAzLjg5NSAzIDVWMTlDMyAyMC4xMDUgMy44OTUgMjEgNSAyMUgxOUMyMC4xMDUgMjEgMjEgMjAuMTA1IDIxIDE5VjVDMjEgMy44OTUgMjAuMTA1IDMgMTkgM0g1ek01IDVIMTlWMTlINVY1ek04LjQxMDE1NjIgNyA3IDguNDEwMTU2MiAxMC41ODk4NDQgMTIgNyAxNS41ODk4NDQgOC40MTAxNTYyIDE3IDEyIDEzLjQxMDE1NiAxNS41ODk4NDQgMTcgMTcgMTUuNTg5ODQ0IDEzLjQxMDE1NiAxMiAxNyA4LjQxMDE1NjIgMTUuNTg5ODQ0IDcgMTIgMTAuNTg5ODQ0IDguNDEwMTU2MiA3eiIvPjwvc3ZnPg==);top:-26.5px;left:.4rem;height:100%}.notices.error::after{position:absolute;content:attr(data-title);font-family:montserrat,sans-serif;top:-26.5px;left:2rem;height:100%}.notices.error a{font-weight:700;color:rgba(116,40,40,.995)}.theme__dark .notices.error a:hover,.theme__dark .notices.error a:active,.theme__dark .notices.error a:focus{color:#ff6188}.theme__light .notices.error a:hover,.theme__light .notices.error a:active,.theme__light .notices.error a:focus{color:#00acd7}.notices.error>table thead{background:#d58181}.notices.error>table th{color:rgba(116,40,40,.995)}.notices.error>table th,.notices.error>table td{padding:5px 15px;border:1px double rgba(148,72,72,.45)}.notices.error p>code,.notices.error li>code,.notices.error td>code,.notices.error code{padding:3px 7px;color:rgba(132,56,56,.995)!important;background-color:#f5d4d4!important}.notices.info{border-top:30px solid #6bb1e0;background:#e6f3fb;color:rgba(47,103,141,.995)!important}.notices.info::before{position:absolute;content:url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjMDAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjIxIiBoZWlnaHQ9IjIxIj48cGF0aCBmaWxsPSIjZTZmM2ZiIiBkPSJNMTIgMkM2LjQ4ODk5NzEgMiAyIDYuNDg4OTk3MSAyIDEyIDIgMTcuNTExMDAzIDYuNDg4OTk3MSAyMiAxMiAyMiAxNy41MTEwMDMgMjIgMjIgMTcuNTExMDAzIDIyIDEyIDIyIDYuNDg4OTk3MSAxNy41MTEwMDMgMiAxMiAyem0wIDJDMTYuNDMwMTIzIDQgMjAgNy41Njk4Nzc0IDIwIDEyIDIwIDE2LjQzMDEyMyAxNi40MzAxMjMgMjAgMTIgMjAgNy41Njk4Nzc0IDIwIDQgMTYuNDMwMTIzIDQgMTJjMC00LjQzMDEyMjYgMy41Njk4Nzc0LTggOC04ek0xMSA3VjloMlY3SDExem0wIDR2NmgyVjExSDExeiIvPjwvc3ZnPg==);top:-26.5px;left:.4rem;height:100%}.notices.info::after{position:absolute;content:attr(data-title);font-family:montserrat,sans-serif;top:-26.5px;left:2rem;height:100%}.notices.info a{font-weight:700;color:rgba(31,87,125,.995)}.theme__dark .notices.info a:hover,.theme__dark .notices.info a:active,.theme__dark .notices.info a:focus{color:#ff6188}.theme__light .notices.info a:hover,.theme__light .notices.info a:active,.theme__light .notices.info a:focus{color:#00acd7}.notices.info>table thead{background:#6bb1e0}.notices.info>table th{color:rgba(31,87,125,.995)}.notices.info>table th,.notices.info>table td{padding:5px 15px;border:1px double rgba(63,119,157,.45)}.notices.info p>code,.notices.info li>code,.notices.info td>code,.notices.info code{padding:3px 7px;color:rgba(47,103,141,.995)!important;background-color:#cce6f7!important}.notices.success{border-top:30px solid #84c578;background:#e8f7e6;color:rgba(72,125,63,.995)!important}.notices.success::before{position:absolute;content:url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjMDAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjIxIiBoZWlnaHQ9IjIxIj48cGF0aCBmaWxsPSIjZThmN2U2IiBkPSJNMTIgMkM2LjQ4ODk5NzEgMiAyIDYuNDg4OTk3MSAyIDEyIDIgMTcuNTExMDAzIDYuNDg4OTk3MSAyMiAxMiAyMiAxNy41MTEwMDMgMjIgMjIgMTcuNTExMDAzIDIyIDEyIDIyIDYuNDg4OTk3MSAxNy41MTEwMDMgMiAxMiAyem0wIDJDMTYuNDMwMTIzIDQgMjAgNy41Njk4Nzc0IDIwIDEyIDIwIDE2LjQzMDEyMyAxNi40MzAxMjMgMjAgMTIgMjAgNy41Njk4Nzc0IDIwIDQgMTYuNDMwMTIzIDQgMTJjMC00LjQzMDEyMjYgMy41Njk4Nzc0LTggOC04ek0xNi4yOTI5NjkgOC4yOTI5Njg4IDEwIDE0LjU4NTkzOCA3LjcwNzAzMTIgMTIuMjkyOTY5IDYuMjkyOTY4OCAxMy43MDcwMzEgMTAgMTcuNDE0MDYyIDE3LjcwNzAzMSA5LjcwNzAzMTIgMTYuMjkyOTY5IDguMjkyOTY4OHoiLz48L3N2Zz4=);top:-26.5px;left:.4rem;height:100%}.notices.success::after{position:absolute;content:attr(data-title);font-family:montserrat,sans-serif;top:-26.5px;left:2rem;height:100%}.notices.success a{font-weight:700;color:rgba(56,109,47,.995)}.theme__dark .notices.success a:hover,.theme__dark .notices.success a:active,.theme__dark .notices.success a:focus{color:#ff6188}.theme__light .notices.success a:hover,.theme__light .notices.success a:active,.theme__light .notices.success a:focus{color:#00acd7}.notices.success>table thead{background:#84c578}.notices.success>table th{color:rgba(56,109,47,.995)}.notices.success>table th,.notices.success>table td{padding:5px 15px;border:1px double rgba(82,141,79,.45)}.notices.success p>code,.notices.success li>code,.notices.success td>code,.notices.success code{padding:3px 7px;color:rgba(72,125,63,.995)!important;background-color:#d3f0cf!important}.alert{padding:.75rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.125rem}.theme__dark .alert-info{background-color:rgba(215,238,249,.4);color:#fcfcfa}.theme__dark .alert-info[data-dir=rtl]{border-right:5px solid #bbdefb}.theme__dark .alert-info[data-dir=ltr]{border-left:5px solid #bbdefb}.theme__dark .alert-success{background-color:rgba(217,239,214,.4);color:#fcfcfa}.theme__dark .alert-success[data-dir=rtl]{border-right:5px solid #c8e6c9}.theme__dark .alert-success[data-dir=ltr]{border-left:5px solid #c8e6c9}.theme__dark .alert-warning{background-color:rgba(255,249,196,.4);color:#fcfcfa}.theme__dark .alert-warning[data-dir=rtl]{border-right:5px solid #ffeb3b}.theme__dark .alert-warning[data-dir=ltr]{border-left:5px solid #ffeb3b}.theme__dark .alert-danger{background-color:rgba(245,221,221,.4);color:#fcfcfa}.theme__dark .alert-danger[data-dir=rtl]{border-right:5px solid #ffcdd2}.theme__dark .alert-danger[data-dir=ltr]{border-left:5px solid #ffcdd2}.theme__light .alert-info{background-color:rgba(215,238,249,.4);color:#242729}.theme__light .alert-info[data-dir=rtl]{border-right:5px solid #bbdefb}.theme__light .alert-info[data-dir=ltr]{border-left:5px solid #bbdefb}.theme__light .alert-success{background-color:rgba(217,239,214,.4);color:#242729}.theme__light .alert-success[data-dir=rtl]{border-right:5px solid #c8e6c9}.theme__light .alert-success[data-dir=ltr]{border-left:5px solid #c8e6c9}.theme__light .alert-warning{background-color:rgba(255,249,196,.4);color:#242729}.theme__light .alert-warning[data-dir=rtl]{border-right:5px solid #ffeb3b}.theme__light .alert-warning[data-dir=ltr]{border-left:5px solid #ffeb3b}.theme__light .alert-danger{background-color:rgba(245,221,221,.4);color:#242729}.theme__light .alert-danger[data-dir=rtl]{border-right:5px solid #ffcdd2}.theme__light .alert-danger[data-dir=ltr]{border-left:5px solid #ffcdd2}#container{display:grid;grid-template-columns:1fr;grid-template-rows:50px auto 1fr auto;grid-column-gap:20px;grid-row-gap:0;grid-template-rows:50px auto 1fr auto;width:100%;max-width:100%;min-height:100vh;margin-left:auto;margin-right:auto;position:relative;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center}.theme__dark #container{color:#fcfcfa}.theme__light #container{color:#242729}.nav{grid-area:1/1/2/2}.top{grid-area:2/1/3/2}.mid{grid-area:3/1/4/2}.bot{grid-area:4/1/5/2}.divider{display:grid;height:100%;grid-template-columns:minmax(200px,240px)minmax(350px,769px)minmax(200px,240px);grid-template-rows:auto;grid-column-gap:0;grid-row-gap:0;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center}@media only screen and (max-width:769px){.divider{grid-template-columns:minmax(0,240px)minmax(0,769px)minmax(0,240px)}}.l{grid-area:1/1/2/2}.m{grid-area:1/2/2/3}.r{grid-area:1/3/2/4}.lm{grid-area:1/1/2/3}.mr{grid-area:1/2/2/4}.lmr{grid-area:1/1/2/4}.sv{display:grid;grid-template-rows:1fr;grid-column-gap:0;grid-row-gap:0}.sv[data-view=full]{grid-template-columns:769px}.sv[data-view=mobile]{width:100%;grid-template-columns:1fr}.blog{grid-area:1/1/2/2}.theme__dark .bot{background-color:#403e41}.theme__light .bot{background-color:#fafafa}.footer{padding:1rem;text-align:center}.theme__dark .footer{border-top:1px solid rgba(243,242,241,.1)}.theme__light .footer{border-top:1px solid rgba(12,13,14,.1)}.footer__section{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-grow:1;-moz-flex-grow:1;-ms-flex-grow:1;flex-grow:1;-webkit-align-items:flex-start;-moz-align-items:flex-start;-ms-align-items:flex-start;-ms-flex-align:flex-start;align-items:flex-start}.footer__section--wrapper{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}@media only screen and (max-width:600px){.footer__section--wrapper{-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;flex-direction:column}}.footer__section--title{font-family:montserrat,sans-serif;font-size:1rem;font-weight:700;margin:1rem 0 .5rem}.footer__section--link{display:block;text-align:left;padding:.15rem .35rem}.footer__contents{width:100%;margin:2rem 0;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:flex-start;-moz-align-items:flex-start;-ms-align-items:flex-start;-ms-flex-align:flex-start;align-items:flex-start;-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.theme__dark .top{background-color:#212121}.theme__light .top{background-color:#eee}.header{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.theme__dark .header__wrapper{border-bottom:1px solid rgba(243,242,241,.1)}.theme__light .header__wrapper{border-bottom:1px solid rgba(12,13,14,.1)}.header__wrapper .title{font-size:3rem;font-weight:900;font-family:montserrat,sans-serif;line-height:3rem;overflow-wrap:break-word;margin:2rem 1.5rem}.theme__dark .header__wrapper .title{color:#fcfcfa}.theme__light .header__wrapper .title{color:#424242}.blog-header{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center;-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.blog-header__title{line-height:1.1;font-weight:900;font-family:montserrat,sans-serif;font-size:3rem;line-height:3rem;overflow-wrap:break-word}.theme__dark .blog-header__title{color:#fcfcfa}.theme__light .blog-header__title{color:#424242}.blog-header__subtitle{line-height:1.2}.blog-header__align-left{-webkit-align-items:flex-start;-moz-align-items:flex-start;-ms-align-items:flex-start;-ms-flex-align:flex-start;align-items:flex-start}.blog-header__align-center{-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center}.blog-header__align-right{-webkit-align-items:flex-end;-moz-align-items:flex-end;-ms-align-items:flex-end;-ms-flex-align:flex-end;align-items:flex-end}.theme__dark .mid{background-color:#212121}.theme__light .mid{background-color:#f7f8f9}.main{width:100%;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center}.theme__dark .main{background-color:#212121}.theme__light .main{background-color:#f7f8f9}.nav{position:relative}.navbar{padding:0 .75rem;height:100%;position:relative;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center}.navbar__wrapper{width:100%;height:50px;position:fixed;left:0;right:0;top:0;z-index:16;color:inherit;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center}.navbar__wrapper[data-bgimg=true]{background-color:transparent}.navbar__wrapper[data-bgimg=false]{box-shadow:0 1px 0 rgba(12,13,14,.1),0 1px 6px rgba(60,65,70,.1)}.theme__dark .navbar__wrapper[data-bgimg=false]{background-color:#403e41}.theme__light .navbar__wrapper[data-bgimg=false]{background-color:#fafafa}.navbar__menu{height:100%;padding:0 .75rem;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}.navbar__menu--wrapper{height:100%;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center}.navbar__menu--item{height:50px;padding:0 .75rem}.navbar__menu--item>a{height:100%;font-family:montserrat,sans-serif;font-size:16.8px;color:inherit;text-decoration:none!important;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center}.theme__dark .navbar__menu--item{color:#fcfcfa}.theme__dark .navbar__menu--item.active{font-weight:700;color:#aed581}.theme__light .navbar__menu--item{color:#242729}.theme__light .navbar__menu--item.active{font-weight:700;color:#007d9c}.navbar__menu--mobile-item{width:100%;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:flex-start;-moz-justify-content:flex-start;-ms-justify-content:flex-start;justify-content:flex-start;-ms-flex-pack:flex-start}.theme__dark .navbar__menu--mobile-item:hover,.theme__dark .navbar__menu--mobile-item:active,.theme__dark .navbar__menu--mobile-item:focus{background-color:#727072}.theme__light .navbar__menu--mobile-item:hover,.theme__light .navbar__menu--mobile-item:active,.theme__light .navbar__menu--mobile-item:focus{background-color:rgba(225,225,225,.4)}.navbar__menu--mobile-item>a{width:100%;font-size:18px;padding:.5rem 1rem}.theme__dark .navbar__menu--mobile-item>a{color:#fcfcfa}.theme__dark .navbar__menu--mobile-item>a:hover,.theme__dark .navbar__menu--mobile-item>a:active,.theme__dark .navbar__menu--mobile-item>a:focus{text-decoration:none;color:#ff6188}.theme__dark .navbar__menu--mobile-item>a.active{font-weight:700;color:#aed581;background-color:#424242}.theme__light .navbar__menu--mobile-item>a{color:#242729}.theme__light .navbar__menu--mobile-item>a:hover,.theme__light .navbar__menu--mobile-item>a:active,.theme__light .navbar__menu--mobile-item>a:focus{text-decoration:none;color:#00acd7}.theme__light .navbar__menu--mobile-item>a.active{font-weight:700;color:#007d9c;background-color:#e0e0e0}.navbar__menu--btn{height:50px;font-size:20px;margin-left:.4rem;margin-right:.5rem;white-space:nowrap;cursor:pointer;border:none;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:flex-end;-moz-align-items:flex-end;-ms-align-items:flex-end;-ms-flex-align:flex-end;align-items:flex-end}.theme__dark .navbar__menu--btn{color:#fcfcfa;background:0 0}.theme__dark .navbar__menu--btn:hover,.theme__dark .navbar__menu--btn:active,.theme__dark .navbar__menu--btn:focus{color:#aed581}.theme__light .navbar__menu--btn{color:#242729;background:0 0}.theme__light .navbar__menu--btn:hover,.theme__light .navbar__menu--btn:active,.theme__light .navbar__menu--btn:focus{color:#007d9c}.navbar__logo{width:100%;height:100%;margin:0 .25rem}.navbar__logo--wrapper{height:100%;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:flex-start;-moz-justify-content:flex-start;-ms-justify-content:flex-start;justify-content:flex-start;-ms-flex-pack:flex-start}.theme__dark .navbar__logo--wrapper{color:#fcfcfa}.theme__dark .navbar__logo--wrapper:hover,.theme__dark .navbar__logo--wrapper:active,.theme__dark .navbar__logo--wrapper:focus{color:#aed581}.theme__light .navbar__logo--wrapper{color:#242729}.theme__light .navbar__logo--wrapper:hover,.theme__light .navbar__logo--wrapper:active,.theme__light .navbar__logo--wrapper:focus{color:#007d9c}.navbar__logo--wrapper a{color:inherit}.navbar__logo--wrapper a:hover,.navbar__logo--wrapper a:active,.navbar__logo--wrapper a:focus{color:inherit;text-decoration:none}.navbar__logo--link{width:32.5px;height:32.5px;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center;-webkit-flex-shrink:0;-moz-flex-shrink:0;-ms-flex-shrink:0;flex-shrink:0}.navbar__logo--text{font-size:20px;margin-left:.5rem;margin-right:1rem;white-space:nowrap;cursor:pointer;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:flex-end;-moz-align-items:flex-end;-ms-align-items:flex-end;-ms-flex-align:flex-end;align-items:flex-end}.theme__dark .navbar__logo--text[data-bgimg=false]{color:#fcfcfa}.theme__light .navbar__logo--text[data-bgimg=false]{color:#242729}.navbar__long--link{width:100%;height:100%;padding:.6rem .2rem;margin:auto .25rem;-webkit-flex-shrink:0;-moz-flex-shrink:0;-ms-flex-shrink:0;flex-shrink:0}.navbar__icons{height:100%;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center}.navbar__icons--icon{width:50px;height:50px;color:inherit;background-color:transparent;outline:none;border:none;cursor:pointer;-webkit-flex-shrink:0;-moz-flex-shrink:0;-ms-flex-shrink:0;flex-shrink:0;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center}.theme__dark .navbar__icons--icon{color:#ccc}.theme__dark .navbar__icons--icon:hover,.theme__dark .navbar__icons--icon:active,.theme__dark .navbar__icons--icon:focus{color:#fcfcfa;background-color:#727072}.theme__dark .navbar__icons--icon>a{height:100%;color:inherit;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center}.theme__light .navbar__icons--icon{color:#535a61}.theme__light .navbar__icons--icon:hover,.theme__light .navbar__icons--icon:active,.theme__light .navbar__icons--icon:focus{color:#242729;background-color:rgba(225,225,225,.4)}.theme__light .navbar__icons--icon>a{height:100%;color:inherit;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center}.navbar__dropdown{height:30px;font-size:17.2px;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center}.navbar__dropdown--content{padding:.25rem 0;min-width:120px;-webkit-box-shadow:0 1px 3px 0 rgba(0,0,0,.4);-moz-box-shadow:0 1px 3px 0 rgba(0,0,0,.4);box-shadow:0 1px 3px 0 rgba(0,0,0,.4)}.theme__dark .navbar__dropdown--content{background-color:#595b5c}.theme__light .navbar__dropdown--content{background-color:#fff}.navbar__dropdown--title{font-size:16.8px;font-family:montserrat,sans-serif;border:none;outline:none;height:50px;cursor:pointer;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center}.navbar__dropdown--title[data-dir=rtl]{margin-right:1rem}.navbar__dropdown--title[data-dir=ltr]{margin-left:1rem}.theme__dark .navbar__dropdown--title{color:#fcfcfa;background-color:#403e41}.theme__light .navbar__dropdown--title{color:#242729;background-color:#fafafa}.navbar__collapse{width:100%;position:absolute;top:50px;left:0;max-height:0;overflow:hidden;-webkit-transition:all .15s ease-out;-moz-transition:all .15s ease-out;-ms-transition:all .15s ease-out;-o-transition:all .15s ease-out;transition:all .15s ease-out}.theme__dark .navbar__collapse{background-color:#403e41}.theme__dark .navbar__collapse[data-open=true]{border-bottom:2px solid rgba(243,242,241,.1)}.theme__dark .navbar__collapse[data-open=false]{border-bottom:none}.theme__light .navbar__collapse{background-color:#fafafa}.theme__light .navbar__collapse[data-open=true]{border-bottom:2px solid rgba(12,13,14,.1)}.theme__light .navbar__collapse[data-open=false]{border-bottom:none}.home__landing{width:100%;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center}@media only screen and (max-width:600px){.home__landing{-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;flex-direction:column}}.home__landing--img{margin:.5rem;z-index:7}.home__landing--txt{margin:2.5rem .5rem;z-index:7}.home__landing--txt .title{font-size:56px;font-weight:900;font-family:montserrat,sans-serif}.home__landing--txt .text{font-size:22px}@media only screen and (max-width:600px){.home__landing--txt{text-align:center}}.home__landing--link{text-decoration:none!important}.home__landing--btn{margin-top:2.5rem;margin-right:.5rem}.home__landing--btn2{margin:.5rem}.home__social{width:100%;padding:1rem 0;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center}.home__social--item{margin:0 .25rem}.home__banner{width:100%;padding:.75rem;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center}.theme__dark .home__banner--wrapper{background-color:#191919}.theme__light .home__banner--wrapper{background-color:#eee}.theme__dark #single-menu[data-dir=ltr]{border-right:1px solid rgba(243,242,241,.1)}.theme__dark #single-menu[data-dir=rtl]{border-left:1px solid rgba(243,242,241,.1)}.theme__light #single-menu[data-dir=ltr]{border-right:1px solid rgba(12,13,14,.1)}.theme__light #single-menu[data-dir=rtl]{border-left:1px solid rgba(12,13,14,.1)}.single{position:relative;width:100%;overflow-wrap:break-word}.single[data-display=block]{display:block}.single[data-display=none]{display:none}.single__title{font-size:3rem;font-weight:900;font-family:montserrat,sans-serif;line-height:3rem;overflow-wrap:break-word;margin:2rem 1rem .25rem}.theme__dark .single__title{color:#fcfcfa}.theme__light .single__title{color:#424242}.single__meta{font-size:.8rem;margin-bottom:1.5rem;padding:0 1rem;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center}.single__infos{margin-right:.5rem;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;-moz-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.single__info{word-break:keep-all;padding:0 .125rem}.single__contents{margin:1rem 0;line-height:1.7;width:inheirt;max-width:inherit}.single__contents--gallery{overflow:hidden}.single__contents>p>a{text-decoration:underline}.single__contents h1,.single__contents h2,.single__contents h3,.single__contents h4,.single__contents h5,.single__contents h6{position:relative;line-height:1.25;padding:0 1rem;font-family:montserrat,sans-serif}.single__contents h1,.single__contents h2{color:inherit;font-weight:900;text-rendering:optimizeLegibility}.theme__dark .single__contents h1,.theme__dark .single__contents h2{color:#ccc}.theme__light .single__contents h1,.theme__light .single__contents h2{color:#607d8b}.theme__dark .single__contents h3,.theme__dark .single__contents h4,.theme__dark .single__contents h5,.theme__dark .single__contents h6{color:#fcfcfa}.single__contents h1{font-size:2.6rem;margin:3.5rem 0 1.75rem}.single__contents h2{font-size:2.2rem;margin:3.2rem 0 1.5rem}.single__contents h3{font-size:1.8rem;margin:2.8rem 0 1.25rem}.single__contents h4{font-size:1.5rem;margin:2.4rem 0 1rem}.single__contents h5{font-size:1.2rem;margin:2rem 0 .8rem}.single__contents h6{font-size:1rem;margin:1.5rem 0 .5rem}.single__contents pre{margin-top:1.6rem;overflow:auto;line-height:1.5;direction:ltr}.theme__dark .single__contents pre{border-top:1px solid rgba(243,242,241,.1);border-bottom:1px solid rgba(243,242,241,.1);scrollbar-width:thin;scrollbar-color:#888 #eee}.theme__dark .single__contents pre::-webkit-scrollbar{width:.45em;height:.45em}.theme__dark .single__contents pre::-webkit-scrollbar-thumb{background:#888}.theme__dark .single__contents pre::-webkit-scrollbar-track{background:#eee}.theme__light .single__contents pre{border-top:1px solid rgba(12,13,14,.1);border-bottom:1px solid rgba(12,13,14,.1);scrollbar-width:thin;scrollbar-color:#cfd8dc #fcfcfa}.theme__light .single__contents pre::-webkit-scrollbar{width:.45em;height:.45em}.theme__light .single__contents pre::-webkit-scrollbar-thumb{background:#cfd8dc}.theme__light .single__contents pre::-webkit-scrollbar-track{background:#fcfcfa}.single__contents pre:not(.chroma){position:relative;margin:1rem 0}.theme__dark .single__contents pre:not(.chroma){border-left:4px solid #595b5c}.theme__light .single__contents pre:not(.chroma){border-left:4px solid #d7dee2}.single__contents div.chroma{position:relative}.single__contents div.chroma:hover .copy-to-clipboard,.single__contents div.chroma:active .copy-to-clipboard,.single__contents div.chroma:focus .copy-to-clipboard{opacity:1}.single__contents p>code:not([class^=language]){padding:.25rem .5rem}.theme__dark .single__contents p>code:not([class^=language]){color:#fcfcfa}.theme__light .single__contents p>code:not([class^=language]){color:#607d8b}.single__contents blockquote{margin:0 1.75rem 1.75rem 1.5rem;padding:0 0 0 1.42188rem;font-size:1.05rem;font-style:italic;line-height:1.75;color:inherit;opacity:.8;position:relative}.theme__dark .single__contents blockquote{border-left:5px solid #fcfcfa}.theme__light .single__contents blockquote{border-left:5px solid #bdbdbd}.single__contents blockquote code:not([class^=language]){padding:3px 7px;margin:0 .25rem}.theme__dark .single__contents blockquote code:not([class^=language]){color:#fcfcfa}.theme__light .single__contents blockquote code:not([class^=language]){color:#607d8b}.single__contents img{display:block;border-radius:.25rem;margin:0 auto}.single__contents p{margin:0 0 10px;padding:0 1rem}.single__contents p code:not([class^=language]){padding:3px 7px;margin:0 .25rem}.theme__dark .single__contents p code:not([class^=language]){color:#fcfcfa}.theme__light .single__contents p code:not([class^=language]){color:#607d8b}.single__contents ul{margin-right:0;margin-top:0;margin-bottom:1rem;padding:0;list-style:disc outside none}.single__contents ol{margin-bottom:1rem}.single__contents[data-dir=ltr] li{margin-left:2rem}.single__contents[data-dir=rtl] li{margin-right:2rem}.single__contents li>code{padding:2px 7px}.theme__dark .single__contents li code:not([class^=language]){color:#fcfcfa}.theme__light .single__contents li code:not([class^=language]){color:#607d8b}.single__contents hr{margin:10px 1rem;border:none;height:1px}.theme__dark .single__contents hr{background:#727072}.theme__light .single__contents hr{background:#bdbdbd}.single__contents dl dt::after{content:':'}.single__contents dd{display:block;margin-inline-start:40px}.single__contents .anchor{cursor:pointer}.single__contents a.footnote-ref{font-size:.75rem;font-weight:700;margin-left:3px}.single__contents a.footnote-ref::before{content:"["}.single__contents a.footnote-ref::after{content:"]"}.single__contents .table-wrapper{overflow-x:auto;margin:1rem}.single__contents .table-wrapper>table{max-width:100%;margin:10px 0;border-spacing:0;box-shadow:1px 1px 3px rgba(0,0,0,.125)}.theme__dark .single__contents .table-wrapper>table thead{background:#1d1e26}.theme__dark .single__contents .table-wrapper>table th{color:#fcfcfa}.theme__dark .single__contents .table-wrapper>table th,.theme__dark .single__contents .table-wrapper>table td{padding:.25rem .5rem;border:1px double #595b5c}.theme__light .single__contents .table-wrapper>table thead{background:#e2e6e9}.theme__light .single__contents .table-wrapper>table th{color:#344952}.theme__light .single__contents .table-wrapper>table th,.theme__light .single__contents .table-wrapper>table td{padding:.25rem .5rem;border:1px double #d7dee2}.single__contents .table-wrapper code:not([class^=language]){padding:3px 7px;margin:0 .25rem}.theme__dark .single__contents .table-wrapper code:not([class^=language]){color:#fcfcfa}.theme__light .single__contents .table-wrapper code:not([class^=language]){color:#607d8b}.single__tags{list-style-type:none;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;-webkit-flex-wrap:wrap;-moz-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-flex-grow:1;-moz-flex-grow:1;-ms-flex-grow:1;flex-grow:1}.single__tag{padding:0 .25rem}code,pre{padding:.25rem .5rem;line-height:1.5;font-family:Consolas,Monaco,Menlo,dejavu sans mono,bitstream vera sans mono,courier new,lucida console,lucida sans typewriter,liberation mono,nimbus mono l,Monaco,Courier,monospace;overflow:auto}code a,pre a{text-decoration:none!important}pre.chroma{padding:.65rem 0}.theme__dark *:not(.chroma) code,.theme__dark *:not(.chroma) pre{color:#eee;background:#2a2c37}.theme__light *:not(.chroma) code,.theme__light *:not(.chroma) pre{color:#344952;background:#f7f8f9}*:not(.chroma) code{padding:0}code:not([class^=language]){padding:3px 0;border-radius:4px}.theme__dark code:not([class^=language]){color:#fcfcfa}.theme__light code:not([class^=language]){color:#607d8b}pre:not(.chroma){overflow:auto}.single__contents>.language-code,li>.language-code{overflow-x:auto;position:relative;margin:1rem 0;direction:ltr}.single__contents>.language-code:hover .copy-to-clipboard,.single__contents>.language-code:active .copy-to-clipboard,.single__contents>.language-code:focus .copy-to-clipboard,li>.language-code:hover .copy-to-clipboard,li>.language-code:active .copy-to-clipboard,li>.language-code:focus .copy-to-clipboard{opacity:1}.single__contents>.language-code::after,li>.language-code::after{position:absolute;top:0;right:0;left:0;padding:2px 7px;width:100%;height:20px;z-index:4;border-top-left-radius:.25rem;border-top-right-radius:.25rem;content:''}.theme__dark .single__contents>.language-code::after,.theme__dark li>.language-code::after{color:#fcfcfa;background:#1d1e26}.theme__light .single__contents>.language-code::after,.theme__light li>.language-code::after{color:#344952;background:#e2e6e9}.highlight>.chroma{margin-bottom:1.5rem;z-index:8;overflow-x:auto;direction:ltr}.theme__dark .highlight>.chroma{color:#eee;background:#2a2c37}.theme__light .highlight>.chroma{color:#344952;background:#f7f8f9}.highlight>.chroma code{padding:0}.highlight>.chroma code[data-lang]::before{position:absolute;top:0;right:0;z-index:12;height:25px;width:100%;display:inline-block;text-align:right;content:attr(data-lang)}.theme__dark .highlight>.chroma code[data-lang]::before{color:#2d2a2e;background:#2d2a2e}.theme__light .highlight>.chroma code[data-lang]::before{color:#fff;background:#fff}.highlight>.chroma code[data-lang]::after{position:absolute;top:2px;right:0;z-index:13;padding:.125rem .25rem;height:25px;font-family:montserrat,sans-serif;font-weight:700;font-size:.85rem;line-height:1.5;display:inline-block;text-transform:capitalize;border-top-left-radius:.2rem;content:attr(data-lang)}.theme__dark .highlight>.chroma code[data-lang]::after{border-top:1px solid #595b5c;border-left:1px solid #595b5c}.theme__light .highlight>.chroma code[data-lang]::after{border-top:1px solid #bdbdbd;border-left:1px solid #bdbdbd}.theme__dark .highlight>.chroma code[data-lang]::after{background:#1d1e26}.theme__light .highlight>.chroma code[data-lang]::after{background:#e2e6e9}.highlight>.chroma table,.highlight>.chroma tr,.highlight>.chroma td{margin:0;padding:0;width:100%;border-collapse:collapse}.highlight>.chroma .lntd:first-child{width:10px;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.highlight>.chroma .lntd:last-child{vertical-align:top}.highlight>.chroma .lnt{margin-left:.2rem;margin-right:.5rem}.theme__dark .highlight>.chroma .lnt{color:#666}.theme__light .highlight>.chroma .lnt{color:#aaa}.highlight>.chroma table.lntable{overflow-x:auto}.theme__dark .highlight>.chroma table.lntable{scrollbar-width:thin;scrollbar-color:#888 #eee}.theme__dark .highlight>.chroma table.lntable::-webkit-scrollbar{width:.45em;height:.45em}.theme__dark .highlight>.chroma table.lntable::-webkit-scrollbar-thumb{background:#888}.theme__dark .highlight>.chroma table.lntable::-webkit-scrollbar-track{background:#eee}.theme__light .highlight>.chroma table.lntable{scrollbar-width:thin;scrollbar-color:#cfd8dc #fcfcfa}.theme__light .highlight>.chroma table.lntable::-webkit-scrollbar{width:.45em;height:.45em}.theme__light .highlight>.chroma table.lntable::-webkit-scrollbar-thumb{background:#cfd8dc}.theme__light .highlight>.chroma table.lntable::-webkit-scrollbar-track{background:#fcfcfa}.theme__dark .highlight>.chroma table.lntable td:first-child{border-left:4px solid #595b5c}.theme__light .highlight>.chroma table.lntable td:first-child{border-left:4px solid #d7dee2}li .highlight>.chroma .lnt:first-child{padding:0 .3rem}li .highlight>.chroma .lnt:not(:first-child){padding:0 .3rem}td:not(.lntd) code{padding:2px 7px!important}table:not(.lntable) td code{padding:2px 7px!important}#list-main{position:relative;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.theme__dark #list-main{background-color:#2d2a2e}.theme__dark #list-main[data-dir=ltr]{border-right:1px solid rgba(243,242,241,.1)}.theme__dark #list-main[data-dir=rtl]{border-left:1px solid rgba(243,242,241,.1)}.theme__light #list-main{background-color:#fff}.theme__light #list-main[data-dir=ltr]{border-right:1px solid rgba(12,13,14,.1)}.theme__light #list-main[data-dir=rtl]{border-left:1px solid rgba(12,13,14,.1)}#list-menu{position:relative}.theme__dark #list-menu[data-dir=ltr]{border-right:1px solid rgba(243,242,241,.1)}.theme__dark #list-menu[data-dir=rtl]{border-left:1px solid rgba(243,242,241,.1)}.theme__light #list-menu[data-dir=ltr]{border-right:1px solid rgba(12,13,14,.1)}.theme__light #list-menu[data-dir=rtl]{border-left:1px solid rgba(12,13,14,.1)}#list-side{position:relative}.list-section__item{margin:auto;padding:.25rem 0;width:95%;border-radius:.2rem}.list-section__item--link{display:inline-block;font-size:1rem;font-family:montserrat,sans-serif;margin-top:.5rem;margin-bottom:.125rem}.list-section__item--desc{font-size:1rem;margin:.25rem 0}.theme__dark .blog{background-color:#2d2a2e}.theme__light .blog{background-color:#fff}.theme__dark .blog__bg{background-color:#2d2a2e}.theme__light .blog__bg{background-color:#fff}.blog__header{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;justify-content:center;-ms-flex-pack:center;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center}.blog .subtitle{margin:.25rem 0} \ No newline at end of file diff --git a/docs/resources/_gen/assets/scss/driplane/sass/main.scss_b4f67ac5085b89b62b54c1923e5a9145.json b/docs/resources/_gen/assets/scss/driplane/sass/main.scss_b4f67ac5085b89b62b54c1923e5a9145.json new file mode 100644 index 0000000..d773bfa --- /dev/null +++ b/docs/resources/_gen/assets/scss/driplane/sass/main.scss_b4f67ac5085b89b62b54c1923e5a9145.json @@ -0,0 +1 @@ +{"Target":"css/main.min.css","MediaType":"text/css","Data":{}} \ No newline at end of file diff --git a/docs/resources/_gen/assets/scss/driplane/scss/slate/print.css.scss_c14439616ffbc3ae1827507340d6c08b.content b/docs/resources/_gen/assets/scss/driplane/scss/slate/print.css.scss_c14439616ffbc3ae1827507340d6c08b.content new file mode 100644 index 0000000..f50c7c1 --- /dev/null +++ b/docs/resources/_gen/assets/scss/driplane/scss/slate/print.css.scss_c14439616ffbc3ae1827507340d6c08b.content @@ -0,0 +1,490 @@ +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + */ +html { + font-family: sans-serif; + /* 1 */ + -ms-text-size-adjust: 100%; + /* 2 */ + -webkit-text-size-adjust: 100%; + /* 2 */ } + +/** + * Remove default margin. + */ +body { + margin: 0; } + +/* HTML5 display definitions + ========================================================================== */ +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; } + +/** + * 1. Correct `inline-block` display not defined in IE 8/9. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ +audio, +canvas, +progress, +video { + display: inline-block; + /* 1 */ + vertical-align: baseline; + /* 2 */ } + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ +audio:not([controls]) { + display: none; + height: 0; } + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ +[hidden], +template { + display: none; } + +/* Links + ========================================================================== */ +/** + * Remove the gray background color from active links in IE 10. + */ +a { + background-color: transparent; } + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ +a:active, +a:hover { + outline: 0; } + +/* Text-level semantics + ========================================================================== */ +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ +abbr[title] { + border-bottom: 1px dotted; } + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ +b, +strong { + font-weight: bold; } + +/** + * Address styling not present in Safari and Chrome. + */ +dfn { + font-style: italic; } + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ +h1 { + font-size: 2em; + margin: 0.67em 0; } + +/** + * Address styling not present in IE 8/9. + */ +mark { + background: #ff0; + color: #000; } + +/** + * Address inconsistent and variable font size in all browsers. + */ +small { + font-size: 80%; } + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; } + +sup { + top: -0.5em; } + +sub { + bottom: -0.25em; } + +/* Embedded content + ========================================================================== */ +/** + * Remove border when inside `a` element in IE 8/9/10. + */ +img { + border: 0; } + +/** + * Correct overflow not hidden in IE 9/10/11. + */ +svg:not(:root) { + overflow: hidden; } + +/* Grouping content + ========================================================================== */ +/** + * Address margin not present in IE 8/9 and Safari. + */ +figure { + margin: 1em 40px; } + +/** + * Address differences between Firefox and other browsers. + */ +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; } + +/** + * Contain overflow in all browsers. + */ +pre { + overflow: auto; } + +/** + * Address odd `em`-unit font size rendering in all browsers. + */ +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; } + +/* Forms + ========================================================================== */ +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + */ +button, +input, +optgroup, +select, +textarea { + color: inherit; + /* 1 */ + font: inherit; + /* 2 */ + margin: 0; + /* 3 */ } + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ +button { + overflow: visible; } + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ +button, +select { + text-transform: none; } + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + */ +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + /* 2 */ + cursor: pointer; + /* 3 */ } + +/** + * Re-set default cursor for disabled elements. + */ +button[disabled], +html input[disabled] { + cursor: default; } + +/** + * Remove inner padding and border in Firefox 4+. + */ +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; } + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ +input { + line-height: normal; } + +/** + * It's recommended that you don't attempt to style these elements. + * Firefox's implementation doesn't respect box-sizing, padding, or width. + * + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + */ +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + /* 1 */ + padding: 0; + /* 2 */ } + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; } + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ +input[type="search"] { + -webkit-appearance: textfield; + /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + /* 2 */ + box-sizing: content-box; } + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; } + +/** + * Define consistent border, margin, and padding. + */ +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; } + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ +legend { + border: 0; + /* 1 */ + padding: 0; + /* 2 */ } + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ +textarea { + overflow: auto; } + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ +optgroup { + font-weight: bold; } + +/* Tables + ========================================================================== */ +/** + * Remove most spacing between table cells. + */ +table { + border-collapse: collapse; + border-spacing: 0; } + +td, +th { + padding: 0; } + +.content > div.highlight { + clear: none; } + +body, .content h3, .content h4, .content h2, .content h1 { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + font-size: 14px; + font-weight: 400; } + +.content h3, .content h4, .content h2, .content h1 { + font-weight: 700; } + +.content pre, .content code { + font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, serif; + font-size: 12px; + line-height: 1.5; } + +.content pre, .content code { + word-break: break-all; + hyphens: auto; } + +@font-face { + font-family: 'slateeee'; + src: url("../fonts/slate.eot?-syv14m"); + src: url("../fonts/slate.eot?#iefix-syv14m") format("embedded-opentype"), url("../fonts/slate.woff2?-syv14m") format("woff2"), url("../fonts/slate.woff?-syv14m") format("woff"), url("../fonts/slate.ttf?-syv14m") format("truetype"), url("../fonts/slate.svg?-syv14m#slate") format("svg"); + font-weight: normal; + font-style: normal; } + +.content aside.success:before, .content aside.notice:before, .content aside.warning:before { + font-family: 'slateeee'; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; } + +.content aside.warning:before { + content: "\e600"; } + +.content aside.notice:before { + content: "\e602"; } + +.content aside.success:before { + content: "\e606"; } + +/* +Copyright 2008-2013 Concur Technologies, Inc. + +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. +*/ +.tocify, .toc-footer, .lang-selector, .search, #nav-button { + display: none; } + +.tocify-wrapper > img { + margin: 0 auto; + display: block; } + +.content { + font-size: 12px; } + .content pre, .content code { + border: 1px solid #999; + border-radius: 5px; + font-size: 0.8em; } + .content pre code { + border: 0; } + .content pre { + padding: 1.3em; } + .content code { + padding: 0.2em; } + .content table { + border: 1px solid #999; } + .content table tr { + border-bottom: 1px solid #999; } + .content table td, .content table th { + padding: 0.7em; } + .content p { + line-height: 1.5; } + .content a { + text-decoration: none; + color: #000; } + .content h1 { + font-size: 2.5em; + padding-top: 0.5em; + padding-bottom: 0.5em; + margin-top: 1em; + margin-bottom: 21px; + border: 2px solid #ccc; + border-width: 2px 0; + text-align: center; } + .content h2 { + font-size: 1.8em; + margin-top: 2em; + border-top: 2px solid #ccc; + padding-top: 0.8em; } + .content h1 + h2, .content h1 + div + h2 { + border-top: none; + padding-top: 0; + margin-top: 0; } + .content h3, .content h4 { + font-size: 0.8em; + margin-top: 1.5em; + margin-bottom: 0.8em; + text-transform: uppercase; } + .content h5, .content h6 { + text-transform: uppercase; } + .content aside { + padding: 1em; + border: 1px solid #ccc; + border-radius: 5px; + margin-top: 1.5em; + margin-bottom: 1.5em; + line-height: 1.6; } + .content aside:before { + vertical-align: middle; + padding-right: 0.5em; + font-size: 14px; } + +@media print { + .copy-clipboard { + display: none; } } + +/*# sourceMappingURL=print.css.map */ \ No newline at end of file diff --git a/docs/resources/_gen/assets/scss/driplane/scss/slate/print.css.scss_c14439616ffbc3ae1827507340d6c08b.json b/docs/resources/_gen/assets/scss/driplane/scss/slate/print.css.scss_c14439616ffbc3ae1827507340d6c08b.json new file mode 100644 index 0000000..3c032d2 --- /dev/null +++ b/docs/resources/_gen/assets/scss/driplane/scss/slate/print.css.scss_c14439616ffbc3ae1827507340d6c08b.json @@ -0,0 +1 @@ +{"Target":"styles/print.css","MediaType":"text/css","Data":{}} \ No newline at end of file diff --git a/docs/resources/_gen/assets/scss/driplane/scss/slate/screen.css.scss_d18af36970f1f09b308ef20ee65e3a03.content b/docs/resources/_gen/assets/scss/driplane/scss/slate/screen.css.scss_d18af36970f1f09b308ef20ee65e3a03.content new file mode 100644 index 0000000..29ed5c2 --- /dev/null +++ b/docs/resources/_gen/assets/scss/driplane/scss/slate/screen.css.scss_d18af36970f1f09b308ef20ee65e3a03.content @@ -0,0 +1,803 @@ +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + */ +html { + font-family: sans-serif; + /* 1 */ + -ms-text-size-adjust: 100%; + /* 2 */ + -webkit-text-size-adjust: 100%; + /* 2 */ } + +/** + * Remove default margin. + */ +body { + margin: 0; } + +/* HTML5 display definitions + ========================================================================== */ +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; } + +/** + * 1. Correct `inline-block` display not defined in IE 8/9. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ +audio, +canvas, +progress, +video { + display: inline-block; + /* 1 */ + vertical-align: baseline; + /* 2 */ } + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ +audio:not([controls]) { + display: none; + height: 0; } + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ +[hidden], +template { + display: none; } + +/* Links + ========================================================================== */ +/** + * Remove the gray background color from active links in IE 10. + */ +a { + background-color: transparent; } + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ +a:active, +a:hover { + outline: 0; } + +/* Text-level semantics + ========================================================================== */ +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ +abbr[title] { + border-bottom: 1px dotted; } + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ +b, +strong { + font-weight: bold; } + +/** + * Address styling not present in Safari and Chrome. + */ +dfn { + font-style: italic; } + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ +h1 { + font-size: 2em; + margin: 0.67em 0; } + +/** + * Address styling not present in IE 8/9. + */ +mark { + background: #ff0; + color: #000; } + +/** + * Address inconsistent and variable font size in all browsers. + */ +small { + font-size: 80%; } + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; } + +sup { + top: -0.5em; } + +sub { + bottom: -0.25em; } + +/* Embedded content + ========================================================================== */ +/** + * Remove border when inside `a` element in IE 8/9/10. + */ +img { + border: 0; } + +/** + * Correct overflow not hidden in IE 9/10/11. + */ +svg:not(:root) { + overflow: hidden; } + +/* Grouping content + ========================================================================== */ +/** + * Address margin not present in IE 8/9 and Safari. + */ +figure { + margin: 1em 40px; } + +/** + * Address differences between Firefox and other browsers. + */ +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; } + +/** + * Contain overflow in all browsers. + */ +pre { + overflow: auto; } + +/** + * Address odd `em`-unit font size rendering in all browsers. + */ +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; } + +/* Forms + ========================================================================== */ +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + */ +button, +input, +optgroup, +select, +textarea { + color: inherit; + /* 1 */ + font: inherit; + /* 2 */ + margin: 0; + /* 3 */ } + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ +button { + overflow: visible; } + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ +button, +select { + text-transform: none; } + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + */ +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + /* 2 */ + cursor: pointer; + /* 3 */ } + +/** + * Re-set default cursor for disabled elements. + */ +button[disabled], +html input[disabled] { + cursor: default; } + +/** + * Remove inner padding and border in Firefox 4+. + */ +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; } + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ +input { + line-height: normal; } + +/** + * It's recommended that you don't attempt to style these elements. + * Firefox's implementation doesn't respect box-sizing, padding, or width. + * + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + */ +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + /* 1 */ + padding: 0; + /* 2 */ } + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; } + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ +input[type="search"] { + -webkit-appearance: textfield; + /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + /* 2 */ + box-sizing: content-box; } + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; } + +/** + * Define consistent border, margin, and padding. + */ +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; } + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ +legend { + border: 0; + /* 1 */ + padding: 0; + /* 2 */ } + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ +textarea { + overflow: auto; } + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ +optgroup { + font-weight: bold; } + +/* Tables + ========================================================================== */ +/** + * Remove most spacing between table cells. + */ +table { + border-collapse: collapse; + border-spacing: 0; } + +td, +th { + padding: 0; } + +.content > div.highlight { + clear: none; } + +html, body, .content h3, .content h4, .content h5, .content h6, .content h2, .content h1 { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + font-size: 14px; + font-weight: 400; } + +.content h3, .content h4, .content h5, .content h6, .content h2, .content h1 { + font-weight: 700; } + +.content pre, .content code { + font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, serif; + font-size: 12px; + line-height: 1.5; } + +.content code { + word-break: break-all; + hyphens: auto; } + +@font-face { + font-family: 'slateeee'; + src: url("../fonts/slate.eot?-syv14m"); + src: url("../fonts/slate.eot?#iefix-syv14m") format("embedded-opentype"), url("../fonts/slate.woff2?-syv14m") format("woff2"), url("../fonts/slate.woff?-syv14m") format("woff"), url("../fonts/slate.ttf?-syv14m") format("truetype"), url("../fonts/slate.svg?-syv14m#slate") format("svg"); + font-weight: normal; + font-style: normal; } + +.toc-wrapper > .search:before, .content aside.success:before, .content aside.notice:before, .content aside.warning:before { + font-family: 'slateeee'; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; } + +.content aside.warning:before { + content: "\e600"; } + +.content aside.notice:before { + content: "\e602"; } + +.content aside.success:before { + content: "\e606"; } + +.toc-wrapper > .search:before { + content: "\e607"; } + +/* +Copyright 2008-2013 Concur Technologies, Inc. + +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. +*/ +html, body { + color: #333; + padding: 0; + margin: 0; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + background-color: #F3F7F9; + height: 100%; + -webkit-text-size-adjust: none; + /* Never autoresize text */ } + +#toc > ul > li > a > span { + float: right; + background-color: #2484FF; + border-radius: 40px; + width: 20px; } + +.toc-wrapper { + transition: left 0.3s ease-in-out; + overflow-y: auto; + overflow-x: hidden; + position: fixed; + z-index: 30; + top: 0; + left: 0; + bottom: 0; + width: 230px; + background-color: #2E3336; + font-size: 13px; + font-weight: bold; } + .toc-wrapper .lang-selector { + display: none; } + .toc-wrapper .lang-selector a { + padding-top: 0.5em; + padding-bottom: 0.5em; } + .toc-wrapper .logo { + display: block; + max-width: 100%; + margin-bottom: 0px; } + .toc-wrapper > .search { + position: relative; } + .toc-wrapper > .search input { + background: #2E3336; + border-width: 0 0 1px 0; + border-color: #666; + padding: 6px 0 6px 20px; + box-sizing: border-box; + margin: 10px 15px; + width: 200px; + outline: none; + color: #fff; + border-radius: 0; + /* ios has a default border radius */ } + .toc-wrapper > .search:before { + position: absolute; + top: 17px; + left: 15px; + color: #fff; } + .toc-wrapper .search-results { + margin-top: 0; + box-sizing: border-box; + height: 0; + overflow-y: auto; + overflow-x: hidden; + transition-property: height, margin; + transition-duration: 180ms; + transition-timing-function: ease-in-out; + background: #1E2224; } + .toc-wrapper .search-results.visible { + height: 30%; + margin-bottom: 1em; } + .toc-wrapper .search-results li { + margin: 1em 15px; + line-height: 1; } + .toc-wrapper .search-results a { + color: #fff; + text-decoration: none; } + .toc-wrapper .search-results a:hover { + text-decoration: underline; } + .toc-wrapper ul, .toc-wrapper li { + list-style: none; + margin: 0; + padding: 0; + line-height: 28px; } + .toc-wrapper li { + color: #fff; + transition-property: background; + transition-timing-function: linear; + transition-duration: 200ms; } + .toc-wrapper .toc-link.active { + background-color: #0F75D4; + color: #fff; } + .toc-wrapper .toc-link.active-parent { + background-color: #1E2224; + color: #fff; } + .toc-wrapper .toc-list-h2 { + display: none; + background-color: #1E2224; + font-weight: 500; } + .toc-wrapper .toc-h2 { + padding-left: 25px; + font-size: 12px; } + .toc-wrapper .toc-footer { + padding: 1em 0; + margin-top: 1em; + border-top: 1px dashed #666; } + .toc-wrapper .toc-footer li, .toc-wrapper .toc-footer a { + color: #fff; + text-decoration: none; } + .toc-wrapper .toc-footer a:hover { + text-decoration: underline; } + .toc-wrapper .toc-footer li { + font-size: 0.8em; + line-height: 1.7; + text-decoration: none; } + +.toc-link, .toc-footer li { + padding: 0 15px 0 15px; + display: block; + overflow-x: hidden; + white-space: nowrap; + text-overflow: ellipsis; + text-decoration: none; + color: #fff; + transition-property: background; + transition-timing-function: linear; + transition-duration: 130ms; } + +#nav-button { + padding: 0 1.5em 5em 0; + display: none; + position: fixed; + top: 0; + left: 0; + z-index: 100; + color: #000; + text-decoration: none; + font-weight: bold; + opacity: 0.7; + line-height: 16px; + transition: left 0.3s ease-in-out; } + #nav-button span { + display: block; + padding: 6px 6px 6px; + background-color: rgba(243, 247, 249, 0.7); + transform-origin: 0 0; + transform: rotate(-90deg) translate(-100%, 0); + border-radius: 0 0 0 5px; } + #nav-button img { + height: 16px; + vertical-align: bottom; } + #nav-button:hover { + opacity: 1; } + #nav-button.open { + left: 230px; } + +.page-wrapper { + margin-left: 230px; + position: relative; + z-index: 10; + background-color: #F3F7F9; + min-height: 100%; + padding-bottom: 1px; } + .page-wrapper .dark-box { + width: 50%; + background-color: #2E3336; + position: absolute; + right: 0; + top: 0; + bottom: 0; } + .page-wrapper .lang-selector { + position: fixed; + z-index: 50; + border-bottom: 5px solid #2E3336; } + +.lang-selector { + display: flex; + background-color: #1E2224; + width: 100%; + font-weight: bold; + overflow-x: auto; } + .lang-selector a { + display: inline; + color: #fff; + text-decoration: none; + padding: 0 10px; + line-height: 30px; + outline: 0; } + .lang-selector a:active, .lang-selector a:focus { + background-color: #111; + color: #fff; } + .lang-selector a.active { + background-color: #2E3336; + color: #fff; } + .lang-selector:after { + content: ''; + clear: both; + display: block; } + +.content { + -webkit-transform: translateZ(0); + position: relative; + z-index: 30; } + .content:after { + content: ''; + display: block; + clear: both; } + .content > h1, .content > h2, .content > h3, .content > h4, .content > h5, .content > h6, .content > p, .content > table, .content > ul, .content > ol, .content > aside, .content > dl { + margin-right: 50%; + padding: 0 28px; + box-sizing: border-box; + display: block; } + .content > ul, .content > ol { + padding-left: 43px; } + .content > h1, .content > h2, .content > div { + clear: both; } + .content h1 { + font-size: 25px; + padding-top: 0.5em; + padding-bottom: 0.5em; + margin-bottom: 21px; + margin-top: 2em; + border-top: 1px solid #ccc; + border-bottom: 1px solid #ccc; + background-color: #fdfdfd; } + .content h1:first-child, .content div:first-child + h1 { + border-top-width: 0; + margin-top: 0; } + .content h2 { + font-size: 19px; + margin-top: 4em; + margin-bottom: 0; + border-top: 1px solid #ccc; + padding-top: 1.2em; + padding-bottom: 1.2em; + background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0)); } + .content h1 + h2, .content h1 + div + h2 { + margin-top: -21px; + border-top: none; } + .content h3, .content h4, .content h5, .content h6 { + font-size: 15px; + margin-top: 2.5em; + margin-bottom: 0.8em; } + .content h4, .content h5, .content h6 { + font-size: 10px; } + .content hr { + margin: 2em 0; + border-top: 2px solid #2E3336; + border-bottom: 2px solid #F3F7F9; } + .content table { + margin-bottom: 1em; + overflow: auto; } + .content table th, .content table td { + text-align: left; + vertical-align: top; + line-height: 1.6; } + .content table th code, .content table td code { + white-space: nowrap; } + .content table th { + padding: 5px 10px; + border-bottom: 1px solid #ccc; + vertical-align: bottom; } + .content table td { + padding: 10px; } + .content table tr:last-child { + border-bottom: 1px solid #ccc; } + .content table tr:nth-child(odd) > td { + background-color: white; } + .content table tr:nth-child(even) > td { + background-color: #fbfcfd; } + .content dt { + font-weight: bold; } + .content dd { + margin-left: 15px; } + .content p, .content li, .content dt, .content dd { + line-height: 1.6; + margin-top: 0; } + .content img { + max-width: 100%; } + .content code { + background-color: rgba(0, 0, 0, 0.05); + padding: 3px; + border-radius: 3px; } + .content pre > code { + background-color: transparent; + padding: 0; } + .content aside { + padding-top: 1em; + padding-bottom: 1em; + margin-top: 1.5em; + margin-bottom: 1.5em; + background: #8fbcd4; + line-height: 1.6; } + .content aside.warning { + background-color: #c97a7e; } + .content aside.success { + background-color: #6ac174; } + .content aside:before { + vertical-align: middle; + padding-right: 0.5em; + font-size: 14px; } + .content .search-highlight { + padding: 2px; + margin: -3px; + border-radius: 4px; + border: 1px solid #F7E633; + background: linear-gradient(to top left, #F7E633 0%, #F1D32F 100%); } + +.content > div.highlight { + clear: none; } + +.content pre, .content blockquote { + background-color: #1E2224; + color: #fff; + margin: 0; + width: 50%; + float: right; + clear: right; + box-sizing: border-box; } + .content pre > p, .content blockquote > p { + margin: 0; } + .content pre a, .content blockquote a { + color: #fff; + text-decoration: none; + border-bottom: dashed 1px #ccc; } + +.content pre { + padding-top: 2em; + padding-bottom: 2em; + padding: 2em 28px; } + +.content blockquote > p { + background-color: #191D1F; + padding: 13px 2em; + color: #eee; } + +@media (max-width: 930px) { + .toc-wrapper { + left: -230px; } + .toc-wrapper.open { + left: 0; } + .page-wrapper { + margin-left: 0; } + #nav-button { + display: block; } + .toc-link { + padding-top: 0.3em; + padding-bottom: 0.3em; } } + +@media (max-width: 700px) { + .dark-box { + display: none; } + .content > h1, .content > h2, .content > h3, .content > h4, .content > h5, .content > h6, .content > p, .content > table, .content > ul, .content > ol, .content > aside, .content > dl { + margin-right: 0; } + .toc-wrapper .lang-selector { + display: block; } + .page-wrapper .lang-selector { + display: none; } + .content pre, .content blockquote { + width: auto; + float: none; } + .content > pre + h1, .content > blockquote + h1, .content > pre + h2, .content > blockquote + h2, .content > pre + h3, .content > blockquote + h3, .content > pre + h4, .content > blockquote + h4, .content > pre + h5, .content > blockquote + h5, .content > pre + h6, .content > blockquote + h6, .content > pre + p, .content > blockquote + p, .content > pre + table, .content > blockquote + table, .content > pre + ul, .content > blockquote + ul, .content > pre + ol, .content > blockquote + ol, .content > pre + aside, .content > blockquote + aside, .content > pre + dl, .content > blockquote + dl { + margin-top: 28px; } } + +.highlight .c, .highlight .cm, .highlight .c1, .highlight .cs { + color: #909090; } + +.highlight, .highlight .w { + background-color: #1E2224; } + +.copy-clipboard { + float: right; + fill: #9DAAB6; + cursor: pointer; + opacity: 0.4; + height: 18px; + width: 18px; } + +.copy-clipboard:hover { + opacity: 0.8; } + +/*# sourceMappingURL=screen.css.map */ \ No newline at end of file diff --git a/docs/resources/_gen/assets/scss/driplane/scss/slate/screen.css.scss_d18af36970f1f09b308ef20ee65e3a03.json b/docs/resources/_gen/assets/scss/driplane/scss/slate/screen.css.scss_d18af36970f1f09b308ef20ee65e3a03.json new file mode 100644 index 0000000..3a607df --- /dev/null +++ b/docs/resources/_gen/assets/scss/driplane/scss/slate/screen.css.scss_d18af36970f1f09b308ef20ee65e3a03.json @@ -0,0 +1 @@ +{"Target":"styles/screen.css","MediaType":"text/css","Data":{}} \ No newline at end of file diff --git a/docs/resources/_gen/assets/scss/scss/slate/print.css.scss_c14439616ffbc3ae1827507340d6c08b.content b/docs/resources/_gen/assets/scss/scss/slate/print.css.scss_c14439616ffbc3ae1827507340d6c08b.content new file mode 100644 index 0000000..f50c7c1 --- /dev/null +++ b/docs/resources/_gen/assets/scss/scss/slate/print.css.scss_c14439616ffbc3ae1827507340d6c08b.content @@ -0,0 +1,490 @@ +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + */ +html { + font-family: sans-serif; + /* 1 */ + -ms-text-size-adjust: 100%; + /* 2 */ + -webkit-text-size-adjust: 100%; + /* 2 */ } + +/** + * Remove default margin. + */ +body { + margin: 0; } + +/* HTML5 display definitions + ========================================================================== */ +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; } + +/** + * 1. Correct `inline-block` display not defined in IE 8/9. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ +audio, +canvas, +progress, +video { + display: inline-block; + /* 1 */ + vertical-align: baseline; + /* 2 */ } + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ +audio:not([controls]) { + display: none; + height: 0; } + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ +[hidden], +template { + display: none; } + +/* Links + ========================================================================== */ +/** + * Remove the gray background color from active links in IE 10. + */ +a { + background-color: transparent; } + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ +a:active, +a:hover { + outline: 0; } + +/* Text-level semantics + ========================================================================== */ +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ +abbr[title] { + border-bottom: 1px dotted; } + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ +b, +strong { + font-weight: bold; } + +/** + * Address styling not present in Safari and Chrome. + */ +dfn { + font-style: italic; } + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ +h1 { + font-size: 2em; + margin: 0.67em 0; } + +/** + * Address styling not present in IE 8/9. + */ +mark { + background: #ff0; + color: #000; } + +/** + * Address inconsistent and variable font size in all browsers. + */ +small { + font-size: 80%; } + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; } + +sup { + top: -0.5em; } + +sub { + bottom: -0.25em; } + +/* Embedded content + ========================================================================== */ +/** + * Remove border when inside `a` element in IE 8/9/10. + */ +img { + border: 0; } + +/** + * Correct overflow not hidden in IE 9/10/11. + */ +svg:not(:root) { + overflow: hidden; } + +/* Grouping content + ========================================================================== */ +/** + * Address margin not present in IE 8/9 and Safari. + */ +figure { + margin: 1em 40px; } + +/** + * Address differences between Firefox and other browsers. + */ +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; } + +/** + * Contain overflow in all browsers. + */ +pre { + overflow: auto; } + +/** + * Address odd `em`-unit font size rendering in all browsers. + */ +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; } + +/* Forms + ========================================================================== */ +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + */ +button, +input, +optgroup, +select, +textarea { + color: inherit; + /* 1 */ + font: inherit; + /* 2 */ + margin: 0; + /* 3 */ } + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ +button { + overflow: visible; } + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ +button, +select { + text-transform: none; } + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + */ +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + /* 2 */ + cursor: pointer; + /* 3 */ } + +/** + * Re-set default cursor for disabled elements. + */ +button[disabled], +html input[disabled] { + cursor: default; } + +/** + * Remove inner padding and border in Firefox 4+. + */ +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; } + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ +input { + line-height: normal; } + +/** + * It's recommended that you don't attempt to style these elements. + * Firefox's implementation doesn't respect box-sizing, padding, or width. + * + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + */ +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + /* 1 */ + padding: 0; + /* 2 */ } + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; } + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ +input[type="search"] { + -webkit-appearance: textfield; + /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + /* 2 */ + box-sizing: content-box; } + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; } + +/** + * Define consistent border, margin, and padding. + */ +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; } + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ +legend { + border: 0; + /* 1 */ + padding: 0; + /* 2 */ } + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ +textarea { + overflow: auto; } + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ +optgroup { + font-weight: bold; } + +/* Tables + ========================================================================== */ +/** + * Remove most spacing between table cells. + */ +table { + border-collapse: collapse; + border-spacing: 0; } + +td, +th { + padding: 0; } + +.content > div.highlight { + clear: none; } + +body, .content h3, .content h4, .content h2, .content h1 { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + font-size: 14px; + font-weight: 400; } + +.content h3, .content h4, .content h2, .content h1 { + font-weight: 700; } + +.content pre, .content code { + font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, serif; + font-size: 12px; + line-height: 1.5; } + +.content pre, .content code { + word-break: break-all; + hyphens: auto; } + +@font-face { + font-family: 'slateeee'; + src: url("../fonts/slate.eot?-syv14m"); + src: url("../fonts/slate.eot?#iefix-syv14m") format("embedded-opentype"), url("../fonts/slate.woff2?-syv14m") format("woff2"), url("../fonts/slate.woff?-syv14m") format("woff"), url("../fonts/slate.ttf?-syv14m") format("truetype"), url("../fonts/slate.svg?-syv14m#slate") format("svg"); + font-weight: normal; + font-style: normal; } + +.content aside.success:before, .content aside.notice:before, .content aside.warning:before { + font-family: 'slateeee'; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; } + +.content aside.warning:before { + content: "\e600"; } + +.content aside.notice:before { + content: "\e602"; } + +.content aside.success:before { + content: "\e606"; } + +/* +Copyright 2008-2013 Concur Technologies, Inc. + +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. +*/ +.tocify, .toc-footer, .lang-selector, .search, #nav-button { + display: none; } + +.tocify-wrapper > img { + margin: 0 auto; + display: block; } + +.content { + font-size: 12px; } + .content pre, .content code { + border: 1px solid #999; + border-radius: 5px; + font-size: 0.8em; } + .content pre code { + border: 0; } + .content pre { + padding: 1.3em; } + .content code { + padding: 0.2em; } + .content table { + border: 1px solid #999; } + .content table tr { + border-bottom: 1px solid #999; } + .content table td, .content table th { + padding: 0.7em; } + .content p { + line-height: 1.5; } + .content a { + text-decoration: none; + color: #000; } + .content h1 { + font-size: 2.5em; + padding-top: 0.5em; + padding-bottom: 0.5em; + margin-top: 1em; + margin-bottom: 21px; + border: 2px solid #ccc; + border-width: 2px 0; + text-align: center; } + .content h2 { + font-size: 1.8em; + margin-top: 2em; + border-top: 2px solid #ccc; + padding-top: 0.8em; } + .content h1 + h2, .content h1 + div + h2 { + border-top: none; + padding-top: 0; + margin-top: 0; } + .content h3, .content h4 { + font-size: 0.8em; + margin-top: 1.5em; + margin-bottom: 0.8em; + text-transform: uppercase; } + .content h5, .content h6 { + text-transform: uppercase; } + .content aside { + padding: 1em; + border: 1px solid #ccc; + border-radius: 5px; + margin-top: 1.5em; + margin-bottom: 1.5em; + line-height: 1.6; } + .content aside:before { + vertical-align: middle; + padding-right: 0.5em; + font-size: 14px; } + +@media print { + .copy-clipboard { + display: none; } } + +/*# sourceMappingURL=print.css.map */ \ No newline at end of file diff --git a/docs/resources/_gen/assets/scss/scss/slate/print.css.scss_c14439616ffbc3ae1827507340d6c08b.json b/docs/resources/_gen/assets/scss/scss/slate/print.css.scss_c14439616ffbc3ae1827507340d6c08b.json new file mode 100644 index 0000000..3c032d2 --- /dev/null +++ b/docs/resources/_gen/assets/scss/scss/slate/print.css.scss_c14439616ffbc3ae1827507340d6c08b.json @@ -0,0 +1 @@ +{"Target":"styles/print.css","MediaType":"text/css","Data":{}} \ No newline at end of file diff --git a/docs/resources/_gen/assets/scss/scss/slate/screen.css.scss_d18af36970f1f09b308ef20ee65e3a03.content b/docs/resources/_gen/assets/scss/scss/slate/screen.css.scss_d18af36970f1f09b308ef20ee65e3a03.content new file mode 100644 index 0000000..29ed5c2 --- /dev/null +++ b/docs/resources/_gen/assets/scss/scss/slate/screen.css.scss_d18af36970f1f09b308ef20ee65e3a03.content @@ -0,0 +1,803 @@ +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + */ +html { + font-family: sans-serif; + /* 1 */ + -ms-text-size-adjust: 100%; + /* 2 */ + -webkit-text-size-adjust: 100%; + /* 2 */ } + +/** + * Remove default margin. + */ +body { + margin: 0; } + +/* HTML5 display definitions + ========================================================================== */ +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; } + +/** + * 1. Correct `inline-block` display not defined in IE 8/9. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ +audio, +canvas, +progress, +video { + display: inline-block; + /* 1 */ + vertical-align: baseline; + /* 2 */ } + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ +audio:not([controls]) { + display: none; + height: 0; } + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ +[hidden], +template { + display: none; } + +/* Links + ========================================================================== */ +/** + * Remove the gray background color from active links in IE 10. + */ +a { + background-color: transparent; } + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ +a:active, +a:hover { + outline: 0; } + +/* Text-level semantics + ========================================================================== */ +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ +abbr[title] { + border-bottom: 1px dotted; } + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ +b, +strong { + font-weight: bold; } + +/** + * Address styling not present in Safari and Chrome. + */ +dfn { + font-style: italic; } + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ +h1 { + font-size: 2em; + margin: 0.67em 0; } + +/** + * Address styling not present in IE 8/9. + */ +mark { + background: #ff0; + color: #000; } + +/** + * Address inconsistent and variable font size in all browsers. + */ +small { + font-size: 80%; } + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; } + +sup { + top: -0.5em; } + +sub { + bottom: -0.25em; } + +/* Embedded content + ========================================================================== */ +/** + * Remove border when inside `a` element in IE 8/9/10. + */ +img { + border: 0; } + +/** + * Correct overflow not hidden in IE 9/10/11. + */ +svg:not(:root) { + overflow: hidden; } + +/* Grouping content + ========================================================================== */ +/** + * Address margin not present in IE 8/9 and Safari. + */ +figure { + margin: 1em 40px; } + +/** + * Address differences between Firefox and other browsers. + */ +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; } + +/** + * Contain overflow in all browsers. + */ +pre { + overflow: auto; } + +/** + * Address odd `em`-unit font size rendering in all browsers. + */ +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; } + +/* Forms + ========================================================================== */ +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + */ +button, +input, +optgroup, +select, +textarea { + color: inherit; + /* 1 */ + font: inherit; + /* 2 */ + margin: 0; + /* 3 */ } + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ +button { + overflow: visible; } + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ +button, +select { + text-transform: none; } + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + */ +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + /* 2 */ + cursor: pointer; + /* 3 */ } + +/** + * Re-set default cursor for disabled elements. + */ +button[disabled], +html input[disabled] { + cursor: default; } + +/** + * Remove inner padding and border in Firefox 4+. + */ +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; } + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ +input { + line-height: normal; } + +/** + * It's recommended that you don't attempt to style these elements. + * Firefox's implementation doesn't respect box-sizing, padding, or width. + * + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + */ +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + /* 1 */ + padding: 0; + /* 2 */ } + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; } + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ +input[type="search"] { + -webkit-appearance: textfield; + /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + /* 2 */ + box-sizing: content-box; } + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; } + +/** + * Define consistent border, margin, and padding. + */ +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; } + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ +legend { + border: 0; + /* 1 */ + padding: 0; + /* 2 */ } + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ +textarea { + overflow: auto; } + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ +optgroup { + font-weight: bold; } + +/* Tables + ========================================================================== */ +/** + * Remove most spacing between table cells. + */ +table { + border-collapse: collapse; + border-spacing: 0; } + +td, +th { + padding: 0; } + +.content > div.highlight { + clear: none; } + +html, body, .content h3, .content h4, .content h5, .content h6, .content h2, .content h1 { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + font-size: 14px; + font-weight: 400; } + +.content h3, .content h4, .content h5, .content h6, .content h2, .content h1 { + font-weight: 700; } + +.content pre, .content code { + font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, serif; + font-size: 12px; + line-height: 1.5; } + +.content code { + word-break: break-all; + hyphens: auto; } + +@font-face { + font-family: 'slateeee'; + src: url("../fonts/slate.eot?-syv14m"); + src: url("../fonts/slate.eot?#iefix-syv14m") format("embedded-opentype"), url("../fonts/slate.woff2?-syv14m") format("woff2"), url("../fonts/slate.woff?-syv14m") format("woff"), url("../fonts/slate.ttf?-syv14m") format("truetype"), url("../fonts/slate.svg?-syv14m#slate") format("svg"); + font-weight: normal; + font-style: normal; } + +.toc-wrapper > .search:before, .content aside.success:before, .content aside.notice:before, .content aside.warning:before { + font-family: 'slateeee'; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; } + +.content aside.warning:before { + content: "\e600"; } + +.content aside.notice:before { + content: "\e602"; } + +.content aside.success:before { + content: "\e606"; } + +.toc-wrapper > .search:before { + content: "\e607"; } + +/* +Copyright 2008-2013 Concur Technologies, Inc. + +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. +*/ +html, body { + color: #333; + padding: 0; + margin: 0; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + background-color: #F3F7F9; + height: 100%; + -webkit-text-size-adjust: none; + /* Never autoresize text */ } + +#toc > ul > li > a > span { + float: right; + background-color: #2484FF; + border-radius: 40px; + width: 20px; } + +.toc-wrapper { + transition: left 0.3s ease-in-out; + overflow-y: auto; + overflow-x: hidden; + position: fixed; + z-index: 30; + top: 0; + left: 0; + bottom: 0; + width: 230px; + background-color: #2E3336; + font-size: 13px; + font-weight: bold; } + .toc-wrapper .lang-selector { + display: none; } + .toc-wrapper .lang-selector a { + padding-top: 0.5em; + padding-bottom: 0.5em; } + .toc-wrapper .logo { + display: block; + max-width: 100%; + margin-bottom: 0px; } + .toc-wrapper > .search { + position: relative; } + .toc-wrapper > .search input { + background: #2E3336; + border-width: 0 0 1px 0; + border-color: #666; + padding: 6px 0 6px 20px; + box-sizing: border-box; + margin: 10px 15px; + width: 200px; + outline: none; + color: #fff; + border-radius: 0; + /* ios has a default border radius */ } + .toc-wrapper > .search:before { + position: absolute; + top: 17px; + left: 15px; + color: #fff; } + .toc-wrapper .search-results { + margin-top: 0; + box-sizing: border-box; + height: 0; + overflow-y: auto; + overflow-x: hidden; + transition-property: height, margin; + transition-duration: 180ms; + transition-timing-function: ease-in-out; + background: #1E2224; } + .toc-wrapper .search-results.visible { + height: 30%; + margin-bottom: 1em; } + .toc-wrapper .search-results li { + margin: 1em 15px; + line-height: 1; } + .toc-wrapper .search-results a { + color: #fff; + text-decoration: none; } + .toc-wrapper .search-results a:hover { + text-decoration: underline; } + .toc-wrapper ul, .toc-wrapper li { + list-style: none; + margin: 0; + padding: 0; + line-height: 28px; } + .toc-wrapper li { + color: #fff; + transition-property: background; + transition-timing-function: linear; + transition-duration: 200ms; } + .toc-wrapper .toc-link.active { + background-color: #0F75D4; + color: #fff; } + .toc-wrapper .toc-link.active-parent { + background-color: #1E2224; + color: #fff; } + .toc-wrapper .toc-list-h2 { + display: none; + background-color: #1E2224; + font-weight: 500; } + .toc-wrapper .toc-h2 { + padding-left: 25px; + font-size: 12px; } + .toc-wrapper .toc-footer { + padding: 1em 0; + margin-top: 1em; + border-top: 1px dashed #666; } + .toc-wrapper .toc-footer li, .toc-wrapper .toc-footer a { + color: #fff; + text-decoration: none; } + .toc-wrapper .toc-footer a:hover { + text-decoration: underline; } + .toc-wrapper .toc-footer li { + font-size: 0.8em; + line-height: 1.7; + text-decoration: none; } + +.toc-link, .toc-footer li { + padding: 0 15px 0 15px; + display: block; + overflow-x: hidden; + white-space: nowrap; + text-overflow: ellipsis; + text-decoration: none; + color: #fff; + transition-property: background; + transition-timing-function: linear; + transition-duration: 130ms; } + +#nav-button { + padding: 0 1.5em 5em 0; + display: none; + position: fixed; + top: 0; + left: 0; + z-index: 100; + color: #000; + text-decoration: none; + font-weight: bold; + opacity: 0.7; + line-height: 16px; + transition: left 0.3s ease-in-out; } + #nav-button span { + display: block; + padding: 6px 6px 6px; + background-color: rgba(243, 247, 249, 0.7); + transform-origin: 0 0; + transform: rotate(-90deg) translate(-100%, 0); + border-radius: 0 0 0 5px; } + #nav-button img { + height: 16px; + vertical-align: bottom; } + #nav-button:hover { + opacity: 1; } + #nav-button.open { + left: 230px; } + +.page-wrapper { + margin-left: 230px; + position: relative; + z-index: 10; + background-color: #F3F7F9; + min-height: 100%; + padding-bottom: 1px; } + .page-wrapper .dark-box { + width: 50%; + background-color: #2E3336; + position: absolute; + right: 0; + top: 0; + bottom: 0; } + .page-wrapper .lang-selector { + position: fixed; + z-index: 50; + border-bottom: 5px solid #2E3336; } + +.lang-selector { + display: flex; + background-color: #1E2224; + width: 100%; + font-weight: bold; + overflow-x: auto; } + .lang-selector a { + display: inline; + color: #fff; + text-decoration: none; + padding: 0 10px; + line-height: 30px; + outline: 0; } + .lang-selector a:active, .lang-selector a:focus { + background-color: #111; + color: #fff; } + .lang-selector a.active { + background-color: #2E3336; + color: #fff; } + .lang-selector:after { + content: ''; + clear: both; + display: block; } + +.content { + -webkit-transform: translateZ(0); + position: relative; + z-index: 30; } + .content:after { + content: ''; + display: block; + clear: both; } + .content > h1, .content > h2, .content > h3, .content > h4, .content > h5, .content > h6, .content > p, .content > table, .content > ul, .content > ol, .content > aside, .content > dl { + margin-right: 50%; + padding: 0 28px; + box-sizing: border-box; + display: block; } + .content > ul, .content > ol { + padding-left: 43px; } + .content > h1, .content > h2, .content > div { + clear: both; } + .content h1 { + font-size: 25px; + padding-top: 0.5em; + padding-bottom: 0.5em; + margin-bottom: 21px; + margin-top: 2em; + border-top: 1px solid #ccc; + border-bottom: 1px solid #ccc; + background-color: #fdfdfd; } + .content h1:first-child, .content div:first-child + h1 { + border-top-width: 0; + margin-top: 0; } + .content h2 { + font-size: 19px; + margin-top: 4em; + margin-bottom: 0; + border-top: 1px solid #ccc; + padding-top: 1.2em; + padding-bottom: 1.2em; + background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0)); } + .content h1 + h2, .content h1 + div + h2 { + margin-top: -21px; + border-top: none; } + .content h3, .content h4, .content h5, .content h6 { + font-size: 15px; + margin-top: 2.5em; + margin-bottom: 0.8em; } + .content h4, .content h5, .content h6 { + font-size: 10px; } + .content hr { + margin: 2em 0; + border-top: 2px solid #2E3336; + border-bottom: 2px solid #F3F7F9; } + .content table { + margin-bottom: 1em; + overflow: auto; } + .content table th, .content table td { + text-align: left; + vertical-align: top; + line-height: 1.6; } + .content table th code, .content table td code { + white-space: nowrap; } + .content table th { + padding: 5px 10px; + border-bottom: 1px solid #ccc; + vertical-align: bottom; } + .content table td { + padding: 10px; } + .content table tr:last-child { + border-bottom: 1px solid #ccc; } + .content table tr:nth-child(odd) > td { + background-color: white; } + .content table tr:nth-child(even) > td { + background-color: #fbfcfd; } + .content dt { + font-weight: bold; } + .content dd { + margin-left: 15px; } + .content p, .content li, .content dt, .content dd { + line-height: 1.6; + margin-top: 0; } + .content img { + max-width: 100%; } + .content code { + background-color: rgba(0, 0, 0, 0.05); + padding: 3px; + border-radius: 3px; } + .content pre > code { + background-color: transparent; + padding: 0; } + .content aside { + padding-top: 1em; + padding-bottom: 1em; + margin-top: 1.5em; + margin-bottom: 1.5em; + background: #8fbcd4; + line-height: 1.6; } + .content aside.warning { + background-color: #c97a7e; } + .content aside.success { + background-color: #6ac174; } + .content aside:before { + vertical-align: middle; + padding-right: 0.5em; + font-size: 14px; } + .content .search-highlight { + padding: 2px; + margin: -3px; + border-radius: 4px; + border: 1px solid #F7E633; + background: linear-gradient(to top left, #F7E633 0%, #F1D32F 100%); } + +.content > div.highlight { + clear: none; } + +.content pre, .content blockquote { + background-color: #1E2224; + color: #fff; + margin: 0; + width: 50%; + float: right; + clear: right; + box-sizing: border-box; } + .content pre > p, .content blockquote > p { + margin: 0; } + .content pre a, .content blockquote a { + color: #fff; + text-decoration: none; + border-bottom: dashed 1px #ccc; } + +.content pre { + padding-top: 2em; + padding-bottom: 2em; + padding: 2em 28px; } + +.content blockquote > p { + background-color: #191D1F; + padding: 13px 2em; + color: #eee; } + +@media (max-width: 930px) { + .toc-wrapper { + left: -230px; } + .toc-wrapper.open { + left: 0; } + .page-wrapper { + margin-left: 0; } + #nav-button { + display: block; } + .toc-link { + padding-top: 0.3em; + padding-bottom: 0.3em; } } + +@media (max-width: 700px) { + .dark-box { + display: none; } + .content > h1, .content > h2, .content > h3, .content > h4, .content > h5, .content > h6, .content > p, .content > table, .content > ul, .content > ol, .content > aside, .content > dl { + margin-right: 0; } + .toc-wrapper .lang-selector { + display: block; } + .page-wrapper .lang-selector { + display: none; } + .content pre, .content blockquote { + width: auto; + float: none; } + .content > pre + h1, .content > blockquote + h1, .content > pre + h2, .content > blockquote + h2, .content > pre + h3, .content > blockquote + h3, .content > pre + h4, .content > blockquote + h4, .content > pre + h5, .content > blockquote + h5, .content > pre + h6, .content > blockquote + h6, .content > pre + p, .content > blockquote + p, .content > pre + table, .content > blockquote + table, .content > pre + ul, .content > blockquote + ul, .content > pre + ol, .content > blockquote + ol, .content > pre + aside, .content > blockquote + aside, .content > pre + dl, .content > blockquote + dl { + margin-top: 28px; } } + +.highlight .c, .highlight .cm, .highlight .c1, .highlight .cs { + color: #909090; } + +.highlight, .highlight .w { + background-color: #1E2224; } + +.copy-clipboard { + float: right; + fill: #9DAAB6; + cursor: pointer; + opacity: 0.4; + height: 18px; + width: 18px; } + +.copy-clipboard:hover { + opacity: 0.8; } + +/*# sourceMappingURL=screen.css.map */ \ No newline at end of file diff --git a/docs/resources/_gen/assets/scss/scss/slate/screen.css.scss_d18af36970f1f09b308ef20ee65e3a03.json b/docs/resources/_gen/assets/scss/scss/slate/screen.css.scss_d18af36970f1f09b308ef20ee65e3a03.json new file mode 100644 index 0000000..3a607df --- /dev/null +++ b/docs/resources/_gen/assets/scss/scss/slate/screen.css.scss_d18af36970f1f09b308ef20ee65e3a03.json @@ -0,0 +1 @@ +{"Target":"styles/screen.css","MediaType":"text/css","Data":{}} \ No newline at end of file diff --git a/docs/static/favicon/android-icon-144x144.png b/docs/static/favicon/android-icon-144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..994ed12e93a29b594bf97c9bdaf26c1d5ab130f4 GIT binary patch literal 8518 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 B6fOV& literal 0 HcmV?d00001 diff --git a/docs/static/favicon/android-icon-192x192.png b/docs/static/favicon/android-icon-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..226b3029b166184022ce62df798142f646489bda GIT binary patch literal 12361 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 PN(Deq%UH7p=M?)N{jv3& literal 0 HcmV?d00001 diff --git a/docs/static/favicon/android-icon-96x96.png b/docs/static/favicon/android-icon-96x96.png new file mode 100644 index 0000000000000000000000000000000000000000..8c04ade06c2188cdb6221c3fbda79514bc84dbb8 GIT binary patch literal 5273 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 literal 0 HcmV?d00001 diff --git a/docs/static/favicon/apple-icon-114x114.png b/docs/static/favicon/apple-icon-114x114.png new file mode 100644 index 0000000000000000000000000000000000000000..0da5bffb2197b9ad569666c290207619aa716853 GIT binary patch literal 6274 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 literal 0 HcmV?d00001 diff --git a/docs/static/favicon/apple-icon-120x120.png b/docs/static/favicon/apple-icon-120x120.png new file mode 100644 index 0000000000000000000000000000000000000000..a01c705fcb258aacc703597fbfee616c854c37b1 GIT binary patch literal 6607 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 Jt+E~Be*mE^Enfft literal 0 HcmV?d00001 diff --git a/docs/static/favicon/apple-icon-144x144.png b/docs/static/favicon/apple-icon-144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..994ed12e93a29b594bf97c9bdaf26c1d5ab130f4 GIT binary patch literal 8518 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 B6fOV& literal 0 HcmV?d00001 diff --git a/docs/static/favicon/apple-icon-152x152.png b/docs/static/favicon/apple-icon-152x152.png new file mode 100644 index 0000000000000000000000000000000000000000..91cd01ba081d99876dd725063230305169dd049c GIT binary patch literal 9320 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 QgY^JVkWrPclQa$cA8oFvJpcdz literal 0 HcmV?d00001 diff --git a/docs/static/favicon/apple-icon-180x180.png b/docs/static/favicon/apple-icon-180x180.png new file mode 100644 index 0000000000000000000000000000000000000000..c573de6d4ff806c0ae452476ae17174c61ccfa77 GIT binary patch literal 12131 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 CdEi(8 literal 0 HcmV?d00001 diff --git a/docs/static/favicon/apple-icon-57x57.png b/docs/static/favicon/apple-icon-57x57.png new file mode 100644 index 0000000000000000000000000000000000000000..18b1b6a02cbdf84137c522cda4fe3942bbf5dac9 GIT binary patch literal 3152 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 literal 0 HcmV?d00001 diff --git a/docs/static/favicon/apple-icon-60x60.png b/docs/static/favicon/apple-icon-60x60.png new file mode 100644 index 0000000000000000000000000000000000000000..d29c96166cf5f8ffcbbb7f3e82d5cda84259299d GIT binary patch literal 3272 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 Nz);^5Q>Et;{U1u7&qx3O literal 0 HcmV?d00001 diff --git a/docs/static/favicon/apple-icon-72x72.png b/docs/static/favicon/apple-icon-72x72.png new file mode 100644 index 0000000000000000000000000000000000000000..7499e3b6ccf1551df063fa094314f33f14f8bd24 GIT binary patch literal 3951 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 PN(Deq%UH7p=M?)N{jv3& literal 0 HcmV?d00001 diff --git a/docs/static/favicon/apple-icon-76x76.png b/docs/static/favicon/apple-icon-76x76.png new file mode 100644 index 0000000000000000000000000000000000000000..27a78d4c4a16fc60429764d47aa9f846071e606c GIT binary patch literal 4121 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 literal 0 HcmV?d00001 diff --git a/docs/static/favicon/apple-icon-precomposed.png b/docs/static/favicon/apple-icon-precomposed.png new file mode 100644 index 0000000000000000000000000000000000000000..552d3b47da04087bfa2002e4c9c3b7c82149155c GIT binary patch literal 12850 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 +#ffffff \ No newline at end of file diff --git a/docs/static/favicon/favicon-16x16.png b/docs/static/favicon/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..4c730be38d735d298a3c1c0d5b870b821c5bed2e GIT binary patch literal 1195 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstUx|vage(c z!@6@aFM%9|WRD45bDP46hOx7_4S6Fo+k-*%fF5)Rz?C z6XN>+|Nq~A{?6Kb;^^fEC$2s9tD2KLas8|J-`;)tnLl}pQ{g0+qAAlip850l|BAgg zU5lr?7Ef_0njBEQ;Pj2xk6(R{Yg_MJG})5bKjSC;F(STBF+R5~-Y zd;f>ee{Mbg9#Fm2rDTfNt}{MQ-#e|nX}#!?#n%7U%U?K`%?PR6bpQE}n~%N+RBdx@ zoab}*h1Z^QuBB70mp!*$@yexaMqtgx+fTl~{rD%j^SDdHLhGeZoJyuAckN$u;H7)n zTF;%Qoz~v4*!5N4Fk-ncvNE9u!SU-tI089jvk*Kn`btM`SUO2C+RD+)ifO z0U298T^vIsE+;22FuSRxv56cwbm~~&ndc9lJbL!fRp`NEaRCt_w-2r^M_E{osH!|< z3cAF^#ALLo$Y9?drhvwVhDDQ%LL6K}-5lH;d}E!34_&`>?c&wT<_0E4W`?ZXGiGW> zMMOp3zH#fObpxx++&Qr^ckkHR?A=p)fN5XdKgLE!wu6cb6CWltcAU`I;85a|!*b-x zjvp-7UA`}QG9_fi*36fZGb69vwA@)~F#V~xh?wZ~Da#sfFiiL&@04wIdmqpPswJ)w zB`Jv|saDBFsX&Us$iT=z*T7QO&?3aZ(#pih%EV0Dz`)AD;FG8A78DJ+`6-!cmAExD zi?nh8HMoInD9%qSDNig)W$?^ROi%SqOwUZtRxr~u*R#;IR4_6yG|@FM)ipFy2sAWP z$S5f(u+rBrFE7{21gQpMplZGRqVzj$Z-E9fNPtWX$tcZDva)i?PcF?(%`3683IHlC zW-wg-f44rG8nB&KRvD?8=@}&qhL%SB3`MO#HR4F-K-Gk2rj%rWlw4k;2y(n6k`mv{ z+|-iFf>Z{utMm)<((N~e`JtKP8v<0tU}$Clj6x$rGqdk&&Pf54@FSTMoLQC1VBq95 zWs%(*pi~%=RA`VVLt17|D$x7-xp^fy`RV#;iDj9|`FX|qh=|coO-ZpdNli8}HL^@I twoFV;GfFZ^OR`8YPfIm4PE1bK1M1KNx=*I~M<&n)22WQ%mvv4FO#pCS?Ogx> literal 0 HcmV?d00001 diff --git a/docs/static/favicon/favicon-32x32.png b/docs/static/favicon/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..160f1079a0c59083a87b327c8a8f4f9e73b0f7ce GIT binary patch literal 1925 zcmZ{jdr(tX9>)(*6{8ep7suAMTO35Hhe5;&6{N@;Bnk3JAbaWT%(|V~KhF7`^ZR{%-{0@d zIVb6eJKKn~iv$2L;<&&bgf-h3h6cn8mtK5Km`?-@E(3tuSGH;WHW7P0%!3Vqs;=FW z8zj%gg9|{^J^*6k0aztmF%tlY$pB3G0zl6JU}w1O-cfr1^w*BKc_KQUZce#$vAlU; zWUBOj4}xXJ7dNSwG|yg5d&iV8(R3D`UD5J#VNom2ZiGbX2$lh(>E1DAy@RvmO@k~v zHzK!XUZwqc^us?AZX;N({9i*FtuDFzIV8$H5nKIYSly<0e>kcV5@jWn^enBce^_3R z%yn>hG+LeqN@m2e!Fd|;psd_Qo}?ugDyRp znA0q;uAh(n}(gX{$)DvB@pWmU6&w|$<4H#w!WQtuG{ei+R< zcDC*1$kLUHcaZ27f@i_fTv(C=qj##?<`$RML>WU&k(?DgXXpRl_==8)HC zUpNGb6fj!APN{J1ed9K%a(tvcRHtL2`MisLvr5fRFH{^!CxYd% zE|j>v7~#&SxzkE!?+W!tEwy$HMzfEcX|I1ek6`Txc9m1t&Yf1dy_sZ{w=oiKGm`Gw z7Y@3JAG9fycb*W;Q`T9TYu^ZWa>3<#BOD>KD}Bqto13~8+MX+2#N7yXjg?g9_IAc? zaGVua=#&xA!;x_25)J41#Py6$t!T9Cu|=a$cmslFz>)cO z*MD_NZG}XYiPuLT^(haZA;>b$op$!k$58w&MpC_f@i47=5sIsT(Hw5%BkkI{tacK? zp1^1!E1}3$F-)z|z-V1g&A94=_VUelEFvT-WnaGG+A~C}S#`|ngr!#zG!sUDyihta zr_>ZTOdXBxg~Do)SUJ0>$)V&mT|Qw~Hs+Yq&A3p_6cunJ&FTLf>wKk-Equ$3=zzl; zm{=7omBW%^Sag$(-w#RcUs_pv*t?KkHO^0d?JDhI;mG>{7-2WoE`Zg3+K~X%9GKxr?cn)3>;2%?xjjN}+rdBCIYxf!ZV~!t zdu3y^RzD7USid7Nkz{E2J~?SLEj#5`{lA)|q&?nax%c3fw4Ejy$6KnLk8(^Zot=G< z9eItp^fsWUXT&uRCe?~<3Q3>fi)yPeqwSY`mHN9L@5>>%JsaL^Xqa>IL~+MSpVwvw zdaCP~$9?CA4b#P_M1qRM%wxlIde+XZijIzxtv~Jb`lZ_ml(o>v`>F6=o4@Tw81Pqv z-;c{DCO(TDsE;t+v^B}hKqgB|J0>$=kZe2@DPsz2N-RlMQ-h%@<+eBmiIjXX)ifg` zOK3>VJnrf3#b$3gzoW0Of6oDVSdeM>ci)8yLr%}f>^GU1fh4f>@U0l>FiM*-s?a9wW}uET&f?1A-MWmy;!e` z*;La?pZlK{`JTnqoAoYT%Cp^jV4z0)T9UKFPQqf(qx}O-f^Det%+TFaqo5~si}4qZ ze=vmf4F}J6~bWVb``qSqCM=v?L_&-%KX|{a*CgRNeG&%sr8+f7VVq zU-Xwm*QGD*qt(mp3PJa&ubQG4?_Jh2kVUIL3~7wNbjn}Rj#bPb+8k`Qrnyqk{Jm}^ z?}IVN1f0KIv+0MI`fkKS_!>t}-~oO(pUy-1gaH&Xg=|iynOjjk$uznRg>GYekW8kN z$x4nx?f)c%garr#BmaNGdD8?#B7wD00SgPnrG6+Ma6q$_+inv4@3dPFScB!&!7l9amq;pId#Rp^v z$|!c6Awu3Cg}gjCAW#_0Cys9!5{d_h2`mHsBtl+TC}#QJi?QSf1kh~wJezMQv_NZ` pA1{#NZxiTG4LB6Yx3c!*@hyl93!=Z>*s_qQ062&{Tm|{Y{TpfFbHV@s literal 0 HcmV?d00001 diff --git a/docs/static/favicon/favicon-96x96.png b/docs/static/favicon/favicon-96x96.png new file mode 100644 index 0000000000000000000000000000000000000000..8c04ade06c2188cdb6221c3fbda79514bc84dbb8 GIT binary patch literal 5273 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 literal 0 HcmV?d00001 diff --git a/docs/static/favicon/favicon.ico b/docs/static/favicon/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..4b2091d214dffb8191d8b570fd07e45ad50f141b GIT binary patch literal 1150 zcmbW1TS${(7{|Y$yKbb5uDk5IE_9pNHg;%AScF$yM0KIdHCN6tkfMvgChj0R*hna% z$klX~W=NZpFvM)wfzTk8K?iGXscmL+-}mqNPBrIU8}I3PpWplbpXd3$k70Jvzp9F% zem~Q)n_>1b40C`QnaCpAX!kRji{Wz8tRvQZ`%z4`J)Y*VXb|WUcnz1&Q z6!thy^eMw6J12}QV>dButHX<74f0QvSRYg%*`q|iS%u|TK=g&^E1x0X`{P*@w@w|z z%tQk?_Bh^0wfJ;f2~5@??$e_8^dWqk7!c2pw1Sh)DsE!xQWJtsEjDtEcsXu@t3?lw z&45fqiCnZ6-BvB)SDFCw6)2vS;$gom`~(D|M3HS97=dD>M_`^2m3WG zO6OUbUrA%cu1B{;hgXSua9fR}UxSal{&+RA5f$+|#2iP!Wj{+if4`*vS00JWC*Wz* zpwD5z?3f9~aTQkYD^Q3jkb9tl+p0$5>Petflrku?a!uZZo$y&y2vE&DtvdACb?C7g zuyjX-{3!7)3e4ZVwmpBe;@Fa4`#${`;d2W3Nn@x(j{wE$rTk6#4kHy-Rry2&xMMVwlL&610Qj2a}8#P{DKQB<+EfdBvi literal 0 HcmV?d00001 diff --git a/docs/static/favicon/logo.png b/docs/static/favicon/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..aceb189791ea81c3b48dedfa954f293fda354e53 GIT binary patch literal 25687 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 literal 0 HcmV?d00001 diff --git a/docs/static/favicon/logo192x192.png b/docs/static/favicon/logo192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..ee8e72900cbc0aded0ddfea41f29f931a5851735 GIT binary patch literal 7716 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 B6fOV& literal 0 HcmV?d00001 diff --git a/docs/static/favicon/ms-icon-150x150.png b/docs/static/favicon/ms-icon-150x150.png new file mode 100644 index 0000000000000000000000000000000000000000..7cac162b77891b76857f94d7f023c053dbb6eb3f GIT binary patch literal 9160 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 eN;SIq;r|12el{NA5 0 { for _, c := range f.cookies { - log.Warning("%#v", c) req.AddCookie(c) } } @@ -143,7 +145,7 @@ func (f *Web) getBodyAsString(r *http.Response) string { return string(body) } -func (f *Web) ParseFeed() error { +func (f *Web) parseURL() error { var txt string extra := make(map[string]string) @@ -161,7 +163,7 @@ func (f *Web) ParseFeed() error { defer r.Body.Close() txt = f.getBodyAsString(r) - meta := utils.GetMetaFromHtml(txt) + meta := utils.GetMetaFromHTML(txt) extra["url"] = f.url extra["title"] = meta.Title extra["description"] = meta.Description @@ -171,7 +173,7 @@ func (f *Web) ParseFeed() error { log.Debug("status -> %s", r.Status) if f.checkStatus == 0 || f.checkStatus == r.StatusCode { if f.textOnly { - txt = utils.ExtractTextFromHtml(txt) + txt = utils.ExtractTextFromHTML(txt) } } else { return fmt.Errorf("unexpected status: %s", r.Status) @@ -186,11 +188,12 @@ func (f *Web) ParseFeed() error { return nil } +// Start propagates a message every time the URL is read func (f *Web) Start() { f.ticker = time.NewTicker(f.frequency) go func() { // first start! - _ = f.ParseFeed() + _ = f.parseURL() for { select { @@ -198,7 +201,7 @@ func (f *Web) Start() { log.Debug("%s: stop arrived on the channel", f.Name()) return case <-f.ticker.C: - _ = f.ParseFeed() + _ = f.parseURL() } } }() @@ -206,6 +209,7 @@ func (f *Web) Start() { f.isRunning = true } +// Stop handles the Feeder shutdown func (f *Web) Stop() { log.Debug("feeder '%s' stream stop", f.Name()) f.stopChan <- true diff --git a/filters/base.go b/filters/base.go index 72695ff..fc69981 100644 --- a/filters/base.go +++ b/filters/base.go @@ -9,15 +9,17 @@ import ( "github.com/evilsocket/islazy/plugin" ) +// FilterFactory identifies a function to instantiate a Filter using the Factory type FilterFactory func(conf map[string]string) (Filter, error) var filterFactories = make(map[string]FilterFactory) +// Filter defines Base methods of the object type Filter interface { setRuleName(name string) setName(name string) setBus(bus EventBus.Bus) - setId(id int32) + setID(id int32) setIsNegative(b bool) Rule() string @@ -27,6 +29,7 @@ type Filter interface { GetIdentifier() string } +// Base is inherited from the feeders type Base struct { rule string name string @@ -36,15 +39,17 @@ type Base struct { cbFilter func(msg *data.Message) (bool, error) } +// Rule returns the rule in which the Filter is found func (f *Base) Rule() string { return f.rule } +// Name returns the Filter's name func (f *Base) Name() string { return f.name } -func (f *Base) setId(id int32) { +func (f *Base) setID(id int32) { f.id = id } @@ -64,10 +69,12 @@ func (f *Base) setIsNegative(b bool) { f.negative = b } +// GetIdentifier returns the Node identifier ID used in the bus func (f *Base) GetIdentifier() string { return fmt.Sprintf("%s:%d", f.name, f.id) } +// Pipe gets a Message from the previous Node and Propagate it to the next one if the Filter's callback will return true func (f *Base) Pipe(msg *data.Message) { log.Debug("[%s::%s] received: %#v", f.rule, f.name, msg) b, err := f.cbFilter(msg) @@ -82,6 +89,7 @@ func (f *Base) Pipe(msg *data.Message) { } } +// Propagate sends the Message to the connected Filters func (f *Base) Propagate(data *data.Message) { data.SetExtra("rule_name", f.Rule()) f.bus.Publish(f.GetIdentifier(), data) @@ -103,13 +111,14 @@ func init() { // https://github.com/evilsocket/shellz/blob/master/plugins/plugin.go#L18 plugin.Defines = map[string]interface{}{ "log": plugins.GetLog(), - "http": plugins.GetHttp(), + "http": plugins.GetHTTP(), "file": plugins.GetFile(), "util": plugins.GetUtil(), "strings": plugins.GetStrings(), } } +// NewFilter creates a new registered Filter from it's name func NewFilter(rule string, name string, conf map[string]string, bus EventBus.Bus, id int32, neg bool) (Filter, error) { if _, ok := filterFactories[name]; ok { f, err := filterFactories[name](conf) @@ -117,7 +126,7 @@ func NewFilter(rule string, name string, conf map[string]string, bus EventBus.Bu f.setRuleName(rule) f.setName(name) f.setBus(bus) - f.setId(id) + f.setID(id) f.setIsNegative(neg) } return f, err diff --git a/filters/cache.go b/filters/cache.go index eec38e6..9304ac3 100644 --- a/filters/cache.go +++ b/filters/cache.go @@ -9,6 +9,7 @@ import ( "time" ) +// Cache handles a cache usable in the rule type Cache struct { sync.Mutex Base @@ -22,6 +23,7 @@ type Cache struct { cache *utils.TTLMap } +// NewCacheFilter is the registered method to instantiate a CacheFilter func NewCacheFilter(p map[string]string) (Filter, error) { f := &Cache{ params: p, @@ -61,6 +63,7 @@ func (f *Cache) getMD5Hash(text string) string { return hex.EncodeToString(hash[:]) } +// DoFilter is the mandatory method used to "filter" the input data.Message func (f *Cache) DoFilter(msg *data.Message) (bool, error) { var text string diff --git a/filters/changed.go b/filters/changed.go index 78067ed..899bc43 100644 --- a/filters/changed.go +++ b/filters/changed.go @@ -7,6 +7,8 @@ import ( "sync" ) +// Changed is a Filter that call the propagation method only if +// the input Message is different from the previous one type Changed struct { sync.Mutex Base @@ -17,6 +19,7 @@ type Changed struct { cache string } +// NewChangedFilter is the registered method to instantiate a ChangedFilter func NewChangedFilter(p map[string]string) (Filter, error) { f := &Changed{ params: p, @@ -36,6 +39,7 @@ func (f *Changed) getMD5Hash(text string) string { return hex.EncodeToString(hash[:]) } +// DoFilter is the mandatory method used to "filter" the input data.Message func (f *Changed) DoFilter(msg *data.Message) (bool, error) { var text string diff --git a/filters/echo.go b/filters/echo.go index 5e8efbe..924daca 100644 --- a/filters/echo.go +++ b/filters/echo.go @@ -6,6 +6,7 @@ import ( "github.com/evilsocket/islazy/log" ) +// Echo is a filter that print the input Message on the logs. type Echo struct { Base @@ -14,6 +15,7 @@ type Echo struct { params map[string]string } +// NewEchoFilter is the registered method to instantiate a EchoFilter func NewEchoFilter(p map[string]string) (Filter, error) { f := &Echo{ params: p, @@ -28,6 +30,7 @@ func NewEchoFilter(p map[string]string) (Filter, error) { return f, nil } +// DoFilter is the mandatory method used to "filter" the input data.Message func (f *Echo) DoFilter(msg *data.Message) (bool, error) { text := msg.GetMessage() if f.printExtra { diff --git a/filters/format.go b/filters/format.go index 41ffc2f..2112c54 100644 --- a/filters/format.go +++ b/filters/format.go @@ -9,6 +9,8 @@ import ( text "text/template" ) +// Format is a Filter that apply a Golang Template to the input Message +// and propagate it to the next Filter type Format struct { Base @@ -18,6 +20,7 @@ type Format struct { params map[string]string } +// NewFormatFilter is the registered method to instantiate a FormatFilter func NewFormatFilter(p map[string]string) (Filter, error) { f := &Format{ params: p, @@ -47,11 +50,12 @@ func NewFormatFilter(p map[string]string) (Filter, error) { if v, ok := f.params["file"]; ok { fpath := v if v, ok := p["general.templates_path"]; !ok { - if r, ok := p["general.rules_path"]; !ok { + r := "" + if r, ok = p["general.rules_path"]; !ok { return nil, fmt.Errorf("NewJsFilter: rules_path or js_path configs not found") - } else { - fpath = filepath.Join(r, fpath) } + fpath = filepath.Join(r, fpath) + } else { fpath = filepath.Join(v, fpath) } @@ -77,6 +81,7 @@ func NewFormatFilter(p map[string]string) (Filter, error) { return f, nil } +// DoFilter is the mandatory method used to "filter" the input data.Message func (f *Format) DoFilter(msg *data.Message) (bool, error) { txt, err := msg.ApplyPlaceholder(f.template) if err != nil { diff --git a/filters/hash.go b/filters/hash.go index e0f6eac..0abd9ae 100644 --- a/filters/hash.go +++ b/filters/hash.go @@ -5,6 +5,7 @@ import ( "regexp" ) +// Hash is a Filter that searches for hashes in the Message type Hash struct { Base @@ -22,6 +23,7 @@ type Hash struct { params map[string]string } +// NewHashFilter is the registered method to instantiate a HashFilter func NewHashFilter(p map[string]string) (Filter, error) { f := &Hash{ params: p, @@ -58,6 +60,7 @@ func NewHashFilter(p map[string]string) (Filter, error) { return f, nil } +// DoFilter is the mandatory method used to "filter" the input data.Message func (f *Hash) DoFilter(msg *data.Message) (bool, error) { text := msg.GetTarget(f.target) match := f.regex.FindAllStringSubmatch(text, -1) diff --git a/filters/http.go b/filters/http.go index e92a897..a88e28e 100644 --- a/filters/http.go +++ b/filters/http.go @@ -17,6 +17,7 @@ import ( "github.com/evilsocket/islazy/log" ) +// HTTP is a filter to handle http requests using the input Message type HTTP struct { Base @@ -36,10 +37,10 @@ type HTTP struct { urlTemplate *template.Template } -func NewHttpFilter(p map[string]string) (Filter, error) { +// NewHTTPFilter is the registered method to instantiate a HttpFilter +func NewHTTPFilter(p map[string]string) (Filter, error) { f := &HTTP{ params: p, - urlFromInput: false, getBody: true, method: "GET", cookieFile: "", @@ -50,9 +51,6 @@ func NewHttpFilter(p map[string]string) (Filter, error) { } f.cbFilter = f.DoFilter - if v, ok := f.params["url_from_input"]; ok && v == "true" { - f.urlFromInput = true - } if v, ok := f.params["text_only"]; ok && v == "true" { f.textOnly = true } @@ -112,22 +110,17 @@ func NewHttpFilter(p map[string]string) (Filter, error) { return f, nil } +// DoFilter is the mandatory method used to "filter" the input data.Message func (f *HTTP) DoFilter(msg *data.Message) (bool, error) { var req *http.Request var err error - text := msg.GetMessage() - client := &http.Client{} urlString := "" - if f.urlFromInput { - urlString = text - } else { - urlString, err = msg.ApplyPlaceholder(f.urlTemplate) - if err != nil { - return false, err - } + urlString, err = msg.ApplyPlaceholder(f.urlTemplate) + if err != nil { + return false, err } var reader io.Reader @@ -185,7 +178,7 @@ func (f *HTTP) DoFilter(msg *data.Message) (bool, error) { if f.getBody { txt := f.getBodyAsString(r) if f.textOnly { - txt = utils.ExtractTextFromHtml(txt) + txt = utils.ExtractTextFromHTML(txt) } msg.SetMessage(txt) } @@ -206,5 +199,5 @@ func (f *HTTP) getBodyAsString(r *http.Response) string { // Set the name of the filter func init() { - register("http", NewHttpFilter) + register("http", NewHTTPFilter) } diff --git a/filters/js.go b/filters/js.go index f03855e..1dfe490 100644 --- a/filters/js.go +++ b/filters/js.go @@ -2,14 +2,14 @@ package filters import ( "fmt" + "path/filepath" + "github.com/Matrix86/driplane/data" "github.com/evilsocket/islazy/plugin" "github.com/robertkrimen/otto" - "path/filepath" - - _ "github.com/Matrix86/driplane/plugins" ) +// Js is a Filter that load a plugin written in Javascript to create a custom Filter type Js struct { Base @@ -21,6 +21,7 @@ type Js struct { params map[string]string } +// NewJsFilter is the registered method to instantiate a JsFilter func NewJsFilter(p map[string]string) (Filter, error) { f := &Js{ params: p, @@ -42,11 +43,12 @@ func NewJsFilter(p map[string]string) (Filter, error) { // If the path specified is relative, we're resolving it with 'rules_path' config if !filepath.IsAbs(f.filepath) { if v, ok := p["general.js_path"]; !ok { - if r, ok := p["general.rules_path"]; !ok { + r := "" + if r, ok = p["general.rules_path"]; !ok { return nil, fmt.Errorf("NewJsFilter: rules_path or js_path configs not found") - } else { - f.filepath = filepath.Join(r, f.filepath) } + f.filepath = filepath.Join(r, f.filepath) + } else { f.filepath = filepath.Join(v, f.filepath) } @@ -66,6 +68,7 @@ func NewJsFilter(p map[string]string) (Filter, error) { return f, nil } +// DoFilter is the mandatory method used to "filter" the input data.Message func (f *Js) DoFilter(msg *data.Message) (bool, error) { triggered := false text := msg.GetMessage() diff --git a/filters/mail.go b/filters/mail.go index b96b155..abb4cf9 100644 --- a/filters/mail.go +++ b/filters/mail.go @@ -2,14 +2,16 @@ package filters import ( "crypto/tls" - "github.com/Matrix86/driplane/data" - "github.com/evilsocket/islazy/log" - gomail "gopkg.in/gomail.v2" "html/template" "strconv" "strings" + + "github.com/Matrix86/driplane/data" + "github.com/evilsocket/islazy/log" + gomail "gopkg.in/gomail.v2" ) +// Mail is a Filter to send e-mail using the input Message type Mail struct { Base @@ -26,6 +28,7 @@ type Mail struct { params map[string]string } +// NewMailFilter is the registered method to instantiate a MailFilter func NewMailFilter(p map[string]string) (Filter, error) { f := &Mail{ params: p, @@ -33,7 +36,7 @@ func NewMailFilter(p map[string]string) (Filter, error) { } f.cbFilter = f.DoFilter - if v, ok := f.params["template"]; ok { + if v, ok := f.params["body"]; ok { t, err := template.New("MailFilterTemplate").Parse(v) if err != nil { return nil, err @@ -74,6 +77,7 @@ func NewMailFilter(p map[string]string) (Filter, error) { return f, nil } +// DoFilter is the mandatory method used to "filter" the input data.Message func (f *Mail) DoFilter(msg *data.Message) (bool, error) { var err error text := msg.GetMessage() diff --git a/filters/override.go b/filters/override.go index 71ba87b..43c0f79 100644 --- a/filters/override.go +++ b/filters/override.go @@ -6,6 +6,9 @@ import ( "text/template" ) + +// Override is a Filter that allow to change the current Message +// before to send it to the next Filter type Override struct { Base @@ -15,6 +18,7 @@ type Override struct { params map[string]string } +// NewOverrideFilter is the registered method to instantiate a OverrideFilter func NewOverrideFilter(p map[string]string) (Filter, error) { f := &Override{ params: p, @@ -40,6 +44,7 @@ func NewOverrideFilter(p map[string]string) (Filter, error) { return f, nil } +// DoFilter is the mandatory method used to "filter" the input data.Message func (f *Override) DoFilter(msg *data.Message) (bool, error) { name, err := msg.ApplyPlaceholder(f.name) if err != nil { diff --git a/filters/system.go b/filters/system.go index 243b827..2528f02 100644 --- a/filters/system.go +++ b/filters/system.go @@ -1,22 +1,23 @@ package filters import ( - "github.com/Matrix86/driplane/data" - "github.com/evilsocket/islazy/log" "os/exec" - "regexp" "text/template" + + "github.com/Matrix86/driplane/data" + "github.com/evilsocket/islazy/log" ) +// System is a Filter to exec a command on the host machine using the input Message type System struct { Base command *template.Template - rExtraCmd *regexp.Regexp params map[string]string } +// NewSystemFilter is the registered method to instantiate a SystemFilter func NewSystemFilter(p map[string]string) (Filter, error) { f := &System{ params: p, @@ -31,11 +32,10 @@ func NewSystemFilter(p map[string]string) (Filter, error) { f.command = t } - f.rExtraCmd = regexp.MustCompile(`(%extra\.[a-z0-9]+%)`) - return f, nil } +// DoFilter is the mandatory method used to "filter" the input data.Message func (f *System) DoFilter(msg *data.Message) (bool, error) { cmd, err := msg.ApplyPlaceholder(f.command) if err != nil { diff --git a/filters/text.go b/filters/text.go index f29c466..95bab45 100644 --- a/filters/text.go +++ b/filters/text.go @@ -7,6 +7,7 @@ import ( "strings" ) +// Text is a Filter to search and extract strings from the input Message type Text struct { Base @@ -19,6 +20,7 @@ type Text struct { params map[string]string } +// NewTextFilter is the registered method to instantiate a TextFilter func NewTextFilter(p map[string]string) (Filter, error) { var err error f := &Text{ @@ -50,6 +52,7 @@ func NewTextFilter(p map[string]string) (Filter, error) { return f, nil } +// DoFilter is the mandatory method used to "filter" the input data.Message func (f *Text) DoFilter(msg *data.Message) (bool, error) { var text string diff --git a/filters/url.go b/filters/url.go index 69feb36..a589a0a 100644 --- a/filters/url.go +++ b/filters/url.go @@ -1,70 +1,79 @@ package filters import ( - "github.com/Matrix86/driplane/data" "regexp" "strings" + + "github.com/Matrix86/driplane/data" ) +// URL is a Filter to search urls in the input Message type URL struct { Base - rUrl *regexp.Regexp + rURL *regexp.Regexp - getHttp bool - getHttps bool - getFtp bool + getHTTP bool + getHTTPS bool + getFTP bool + target string - extractUrl bool + extractURL bool params map[string]string } -func NewUrlFilter(p map[string]string) (Filter, error) { +// NewURLFilter is the registered method to instantiate a UrlFilter +func NewURLFilter(p map[string]string) (Filter, error) { f := &URL{ params: p, - getHttp: true, - getHttps: true, - getFtp: true, - extractUrl: true, + getHTTP: true, + getHTTPS: true, + getFTP: true, + extractURL: true, + target: "main", } f.cbFilter = f.DoFilter - f.rUrl = regexp.MustCompile(`(?i)((http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?(([a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5})|([0-9]{1,3}\.){3}[0-9]{1,3})(:[0-9]{1,5})?(\/[^\s]+)?)`) + f.rURL = regexp.MustCompile(`(?i)((http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?(([a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5})|([0-9]{1,3}\.){3}[0-9]{1,3})(:[0-9]{1,5})?(\/[^\s]+)?)`) if v, ok := f.params["http"]; ok && v == "false" { - f.getHttp = false + f.getHTTP = false } if v, ok := f.params["https"]; ok && v == "false" { - f.getHttps = false + f.getHTTPS = false } if v, ok := f.params["ftp"]; ok && v == "false" { - f.getFtp = false + f.getFTP = false } if v, ok := f.params["extract"]; ok && v == "false" { - f.extractUrl = false + f.extractURL = false + } + if v, ok := f.params["target"]; ok { + f.target = v } return f, nil } +// DoFilter is the mandatory method used to "filter" the input data.Message func (f *URL) DoFilter(msg *data.Message) (bool, error) { - text := msg.GetMessage() + text := msg.GetTarget(f.target) found := false - match := f.rUrl.FindAllStringSubmatch(text, -1) + match := f.rURL.FindAllStringSubmatch(text, -1) if match != nil { for _, m := range match { mm := m[0] - if f.getHttp && strings.HasPrefix(strings.ToLower(mm), "http://") { + if f.getHTTP && strings.HasPrefix(strings.ToLower(mm), "http://") { found = true - } else if f.getHttps && strings.HasPrefix(strings.ToLower(mm), "https://") { + } else if f.getHTTPS && strings.HasPrefix(strings.ToLower(mm), "https://") { found = true - } else if f.getFtp && strings.HasPrefix(strings.ToLower(mm), "ftp://") { + } else if f.getFTP && strings.HasPrefix(strings.ToLower(mm), "ftp://") { found = true } - if f.extractUrl { + if f.extractURL { clone := msg.Clone() clone.SetMessage(mm) clone.SetExtra("fulltext", text) @@ -81,5 +90,5 @@ func (f *URL) DoFilter(msg *data.Message) (bool, error) { // Set the name of the filter func init() { - register("url", NewUrlFilter) + register("url", NewURLFilter) } diff --git a/filters/utils/global_ttl_map.go b/filters/utils/global_ttl_map.go index 0d388e5..17ec42e 100644 --- a/filters/utils/global_ttl_map.go +++ b/filters/utils/global_ttl_map.go @@ -5,6 +5,7 @@ import ( "time" ) +// GlobalTTLMap is a cache shared between all the rules type GlobalTTLMap struct { Cache *TTLMap } @@ -14,6 +15,7 @@ var ( once sync.Once ) +// GetGlobalTTLMapInstance returns the unique GlobalTTLMap (singleton) func GetGlobalTTLMapInstance(gcdelay time.Duration) *GlobalTTLMap { once.Do(func() { instance = &GlobalTTLMap{ diff --git a/filters/utils/ttl_map.go b/filters/utils/ttl_map.go index a3ea98d..1b19634 100644 --- a/filters/utils/ttl_map.go +++ b/filters/utils/ttl_map.go @@ -14,6 +14,7 @@ func (i *item) expired() bool { return i.expiration <= time.Now().Unix() } +// TTLMap is a cache with ttl type TTLMap struct { sync.RWMutex @@ -21,6 +22,7 @@ type TTLMap struct { gcdelay time.Duration } +// NewTTLMap creates a TTLMap instance func NewTTLMap(gcdelay time.Duration) (m *TTLMap) { m = &TTLMap{ dict: make(map[interface{}]*item, 0), @@ -30,7 +32,7 @@ func NewTTLMap(gcdelay time.Duration) (m *TTLMap) { // Cleaning method is called every X seconds because we // check if an item is expired in the Get method go func() { - for _ = range time.Tick(gcdelay) { + for range time.Tick(gcdelay) { m.Lock() for k, v := range m.dict { if v.expired() { @@ -43,12 +45,14 @@ func NewTTLMap(gcdelay time.Duration) (m *TTLMap) { return } +// Len returns the number of cached keys func (m *TTLMap) Len() int { m.RLock() defer m.RUnlock() return len(m.dict) } +// Put inserts a key => value pair in the cache func (m *TTLMap) Put(k, v interface{}, ttl int64) { m.Lock() defer m.Unlock() @@ -65,6 +69,7 @@ func (m *TTLMap) Put(k, v interface{}, ttl int64) { } } +// Get returns the value of the associated key from the cache func (m *TTLMap) Get(k string) (interface{}, bool) { m.RLock() defer m.RUnlock() diff --git a/go.sum b/go.sum index e16bf32..5f682b9 100644 --- a/go.sum +++ b/go.sum @@ -25,6 +25,7 @@ github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASu github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/matrix86/driplane v0.0.0-20200916200730-47f56c53a63e h1:sEYoFzMOhJQHyV9n1ZjWbYLs+l5Fw6PQ7WRjp7Q39es= github.com/mmcdole/gofeed v1.0.0 h1:PHqwr8fsEm8xarj9s53XeEAFYhRM3E9Ib7Ie766/LTE= github.com/mmcdole/gofeed v1.0.0/go.mod h1:tkVcyzS3qVMlQrQxJoEH1hkTiuo9a8emDzkMi7TZBu0= github.com/mmcdole/goxpp v0.0.0-20181012175147-0068e33feabf h1:sWGE2v+hO0Nd4yFU/S/mDBM5plIU8v/Qhfz41hkDIAI= diff --git a/plugins/file.go b/plugins/file.go index 40a7e97..c8268f7 100644 --- a/plugins/file.go +++ b/plugins/file.go @@ -6,114 +6,123 @@ import ( "os" ) -type filePackage struct{} +// FilePackage contains file manipulation methods +type FilePackage struct{} -func GetFile() *filePackage { - return &filePackage{} +// GetFile returns the FilePackage struct +func GetFile() *FilePackage { + return &FilePackage{} } -type fileResponse struct { +// FileResponse contains the return values +type FileResponse struct { Error error Status bool } -func (c *filePackage) Copy(src, dst string) (fileResponse) { +// Copy handles the copy of a file to another file +func (c *FilePackage) Copy(src, dst string) FileResponse { sourceFileStat, err := os.Stat(src) if err != nil { - return fileResponse{Error: err} + return FileResponse{Error: err} } if !sourceFileStat.Mode().IsRegular() { - return fileResponse{Error: fmt.Errorf("%s is not a regular file", src)} + return FileResponse{Error: fmt.Errorf("%s is not a regular file", src)} } source, err := os.Open(src) if err != nil { - return fileResponse{Error: err} + return FileResponse{Error: err} } defer source.Close() destination, err := os.Create(dst) if err != nil { - return fileResponse{Error: err} + return FileResponse{Error: err} } defer destination.Close() _, err = io.Copy(destination, source) if err != nil { - return fileResponse{Error: err} + return FileResponse{Error: err} } - return fileResponse{Status: true} + return FileResponse{Status: true} } -func (c *filePackage) Move(src, dst string) (fileResponse) { +// Move renames a file +func (c *FilePackage) Move(src, dst string) FileResponse { sourceFileStat, err := os.Stat(src) if err != nil { - return fileResponse{Error: err} + return FileResponse{Error: err} } if !sourceFileStat.Mode().IsRegular() { - return fileResponse{Error: fmt.Errorf("%s is not a regular file", src)} + return FileResponse{Error: fmt.Errorf("%s is not a regular file", src)} } err = os.Rename(src, dst) if err != nil { - return fileResponse{Error: err} + return FileResponse{Error: err} } - return fileResponse{Status: true} + return FileResponse{Status: true} } -func (c *filePackage) Truncate(filename string, size int64) fileResponse { +// Truncate set file length to size +func (c *FilePackage) Truncate(filename string, size int64) FileResponse { sourceFileStat, err := os.Stat(filename) if err != nil { - return fileResponse{Error: err} + return FileResponse{Error: err} } if !sourceFileStat.Mode().IsRegular() { - return fileResponse{Error: fmt.Errorf("%s is not a regular file", filename)} + return FileResponse{Error: fmt.Errorf("%s is not a regular file", filename)} } err = os.Truncate(filename, size) if err != nil { - return fileResponse{Error: err} + return FileResponse{Error: err} } - return fileResponse{Status: true} + return FileResponse{Status: true} } -func (c *filePackage) Delete(filename string) fileResponse { +// Delete removes a file +func (c *FilePackage) Delete(filename string) FileResponse { sourceFileStat, err := os.Stat(filename) if err != nil { - return fileResponse{Error: err} + return FileResponse{Error: err} } if !sourceFileStat.Mode().IsRegular() { - return fileResponse{Error: fmt.Errorf("%s is not a regular file", filename)} + return FileResponse{Error: fmt.Errorf("%s is not a regular file", filename)} } err = os.Remove(filename) if err != nil { - return fileResponse{Error: err} + return FileResponse{Error: err} } - return fileResponse{Status: true} + return FileResponse{Status: true} } -func (c *filePackage) Exists(filename string) fileResponse { +// Exists returns true if the file exists +func (c *FilePackage) Exists(filename string) FileResponse { sourceFileStat, err := os.Stat(filename) if os.IsNotExist(err) { - return fileResponse{Status: false} + return FileResponse{Status: false} } - return fileResponse{Status: !sourceFileStat.IsDir()} + return FileResponse{Status: !sourceFileStat.IsDir()} } -func (c *filePackage) AppendString(filename string, text string) fileResponse { +// AppendString opens the file in appending mode and write text on it +func (c *FilePackage) AppendString(filename string, text string) FileResponse { f, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { - return fileResponse{Error: err, Status: false} + return FileResponse{Error: err, Status: false} } defer f.Close() if _, err := f.WriteString(text); err != nil { - return fileResponse{Error: err, Status: false} + return FileResponse{Error: err, Status: false} } - return fileResponse{Status: true} + return FileResponse{Status: true} } diff --git a/plugins/http.go b/plugins/http.go index dd24e0f..196e293 100644 --- a/plugins/http.go +++ b/plugins/http.go @@ -14,20 +14,24 @@ import ( "github.com/evilsocket/islazy/log" ) -type httpPackage struct {} +// HTTPPackage contains all the methods to perform http requests +type HTTPPackage struct{} -func GetHttp() *httpPackage { - return &httpPackage{} +// GetHTTP returns the HTTPPackage +func GetHTTP() *HTTPPackage { + return &HTTPPackage{} } -type httpResponse struct { +// HTTPResponse contains the return values +type HTTPResponse struct { Error error Response *http.Response Raw []byte Body string + Status bool } -func (c *httpPackage) createRequest(method string, uri string, headers interface{}, data interface{}) (*http.Request, error) { +func (c *HTTPPackage) createRequest(method string, uri string, headers interface{}, data interface{}) (*http.Request, error) { var reader io.Reader if data != nil { @@ -68,83 +72,90 @@ func (c *httpPackage) createRequest(method string, uri string, headers interface return req, nil } -func (c *httpPackage) Request(method string, uri string, headers interface{}, data interface{}) httpResponse { +// Request performs a HTTP request +func (c *HTTPPackage) Request(method string, uri string, headers interface{}, data interface{}) HTTPResponse { client := &http.Client{} req, err := c.createRequest(method, uri, headers, data) if err != nil { log.Error("http.createRequest : %s", err) - return httpResponse{Error: err} + return HTTPResponse{Error: err, Status: false} } resp, err := client.Do(req) if err != nil { - return httpResponse{Error: err} + return HTTPResponse{Error: err, Status: false} } defer resp.Body.Close() raw, err := ioutil.ReadAll(resp.Body) if err != nil { - return httpResponse{Error: err} + return HTTPResponse{Error: err, Status: false} } - return httpResponse{ + return HTTPResponse{ Error: nil, Response: resp, Raw: raw, Body: string(raw), + Status: true, } } -func (c *httpPackage) Get(url string, headers map[string]string) httpResponse { +// Get performs a GET request +func (c *HTTPPackage) Get(url string, headers map[string]string) HTTPResponse { return c.Request("GET", url, headers, nil) } -func (c *httpPackage) Post(url string, headers map[string]string, data interface{}) httpResponse { +// Post performs a POST request +func (c *HTTPPackage) Post(url string, headers map[string]string, data interface{}) HTTPResponse { return c.Request("POST", url, headers, data) } -func (c *httpPackage) DownloadFile(filepath string, method string, uri string, headers interface{}, data interface{}) httpResponse { +// DownloadFile gets a file from an URL and store in on disk +func (c *HTTPPackage) DownloadFile(filepath string, method string, uri string, headers interface{}, data interface{}) HTTPResponse { client := &http.Client{} req, err := c.createRequest(method, uri, headers, data) if err != nil { log.Error("http.createRequest : %s", err) - return httpResponse{Error: err} + return HTTPResponse{Error: err, Status: false} } resp, err := client.Do(req) if err != nil { - return httpResponse{Error: err} + return HTTPResponse{Error: err, Status: false} } defer resp.Body.Close() out, err := os.Create(filepath) if err != nil { log.Error("http.DownloadFile: %s", err) - return httpResponse{Error: err} + return HTTPResponse{Error: err, Status: false} } defer out.Close() _, err = io.Copy(out, resp.Body) if err != nil { log.Error("%s", err) - return httpResponse{Error: err} + return HTTPResponse{Error: err, Status: false} } - return httpResponse{ + return HTTPResponse{ Error: nil, Response: resp, + Status: true, } } -func (c *httpPackage) UploadFile(filename string, fieldname string, method string, uri string, headers interface{}, data interface{}) httpResponse { +// UploadFile sends a file to an URL +func (c *HTTPPackage) UploadFile(filename string, fieldname string, method string, uri string, headers interface{}, data interface{}) HTTPResponse { client := &http.Client{} file, err := os.Open(filename) if err != nil { log.Error("%s", err) - return httpResponse{Error: err} + return HTTPResponse{Error: err, Status: false} } defer file.Close() @@ -154,12 +165,12 @@ func (c *httpPackage) UploadFile(filename string, fieldname string, method strin part, err := writer.CreateFormFile(fieldname, filepath.Base(filename)) if err != nil { log.Error("%s", err) - return httpResponse{Error: err} + return HTTPResponse{Error: err, Status: false} } _, err = io.Copy(part, file) if err != nil { log.Error("http.createRequest : io.Copy : %s", err) - return httpResponse{Error: err} + return HTTPResponse{Error: err, Status: false} } if v, ok := data.(map[string]interface{}); ok { @@ -173,13 +184,13 @@ func (c *httpPackage) UploadFile(filename string, fieldname string, method strin err = writer.Close() if err != nil { log.Error("http.UploadFile : writer.Close : %s", err) - return httpResponse{Error: err} + return HTTPResponse{Error: err, Status: false} } req, err := c.createRequest(method, uri, headers, &bodyfile) if err != nil { log.Error("http.createRequest : %s", err) - return httpResponse{Error: err} + return HTTPResponse{Error: err, Status: false} } req.Header.Set("Content-Type", writer.FormDataContentType()) @@ -187,19 +198,20 @@ func (c *httpPackage) UploadFile(filename string, fieldname string, method strin resp, err := client.Do(req) if err != nil { log.Error("http.Upload client do : %s", err) - return httpResponse{Error: err} + return HTTPResponse{Error: err, Status: false} } defer resp.Body.Close() raw, err := ioutil.ReadAll(resp.Body) if err != nil { - return httpResponse{Error: err} + return HTTPResponse{Error: err, Status: false} } - return httpResponse{ + return HTTPResponse{ Error: nil, Response: resp, Raw: raw, Body: string(raw), + Status: true, } } diff --git a/plugins/log.go b/plugins/log.go index 609bdf3..7f61f18 100644 --- a/plugins/log.go +++ b/plugins/log.go @@ -4,20 +4,25 @@ import ( "github.com/evilsocket/islazy/log" ) +// LogPackage contains logs methods type LogPackage struct{} +// GetLog returns the LogPackage func GetLog() *LogPackage { return &LogPackage{} } +// Info prints an info line on the logs func (l *LogPackage) Info(format string, a ...interface{}) { log.Info(format, a...) } +// Error prints an error line on the logs func (l *LogPackage) Error(format string, a ...interface{}) { log.Error(format, a...) } +// Debug prints a debug line on the logs func (l *LogPackage) Debug(format string, a ...interface{}) { log.Debug(format, a...) } diff --git a/plugins/strings.go b/plugins/strings.go index 905dde8..bbb9df3 100644 --- a/plugins/strings.go +++ b/plugins/strings.go @@ -4,20 +4,24 @@ import ( "strings" ) -type stringsPackage struct {} +// StringsPackage contains string manipulation methods +type StringsPackage struct {} -func GetStrings() *stringsPackage { - return &stringsPackage{} +// GetStrings returns a StringsPackage +func GetStrings() *StringsPackage { + return &StringsPackage{} } -type stringsResponse struct { +// StringsResponse contains the return values +type StringsResponse struct { Error error Status bool } -func (c *stringsPackage) StartsWith(str, substr string) stringsResponse { +// StartsWith returns true if a string start with a substring +func (c *StringsPackage) StartsWith(str, substr string) StringsResponse { ret := strings.HasPrefix(str, substr) - return stringsResponse{ + return StringsResponse{ Error: nil, Status: ret, } diff --git a/plugins/util.go b/plugins/util.go index 98b4865..b45e382 100644 --- a/plugins/util.go +++ b/plugins/util.go @@ -5,21 +5,35 @@ import ( "time" ) -type utilPackage struct {} +// UtilPackage contains useful generic methods +type UtilPackage struct {} -func GetUtil() *utilPackage { - return &utilPackage{} +// GetUtil returns an UtilPackage +func GetUtil() *UtilPackage { + return &UtilPackage{} } -type utilResponse struct { +// UtilResponse contains the return values +type UtilResponse struct { Error error Status bool + Value string } -func (c *utilPackage) Sleep(seconds int) { +// Sleep call Sleep method for N seconds +func (c *UtilPackage) Sleep(seconds int) UtilResponse { time.Sleep(time.Duration(seconds) * time.Second) + return UtilResponse{ + Error: nil, + Status: true, + } } -func (c *utilPackage) Getenv(name string) string { - return os.Getenv(name) +// Getenv returns an environment variable if it exists +func (c *UtilPackage) Getenv(name string) UtilResponse { + return UtilResponse{ + Error: nil, + Status: true, + Value: os.Getenv(name), + } } \ No newline at end of file diff --git a/utils/cookie.go b/utils/cookie.go index cd575a2..e2b26cb 100644 --- a/utils/cookie.go +++ b/utils/cookie.go @@ -8,6 +8,7 @@ import ( "time" ) +// Cookies maps the json file exported from Chrome containing the cookies type Cookies []struct { Domain string `json:"domain"` ExpirationDate float64 `json:"expirationDate,omitempty"` @@ -23,6 +24,7 @@ type Cookies []struct { ID int `json:"id"` } +// ParseCookieFile transforms JSON file in slice of http.Cookie func ParseCookieFile(filename string) ([]*http.Cookie, error) { var cookies Cookies jsonFile, err := os.Open(filename) diff --git a/utils/html.go b/utils/html.go index 7e1aeae..6c1561d 100644 --- a/utils/html.go +++ b/utils/html.go @@ -6,6 +6,7 @@ import ( "strings" ) +// HTMLMeta contains information from the HTML page type HTMLMeta struct { Title string `json:"title"` Description string `json:"description"` @@ -13,7 +14,8 @@ type HTMLMeta struct { SiteName string `json:"site_name"` } -func GetMetaFromHtml(s string) *HTMLMeta { +// GetMetaFromHTML extracts info from an HTML page and store them on a HTMLMeta struct +func GetMetaFromHTML(s string) *HTMLMeta { z := html.NewTokenizer(strings.NewReader(s)) titleFound := false hm := &HTMLMeta{} @@ -82,7 +84,8 @@ func extractMetaProperty(t html.Token, prop string) (content string, ok bool) { return } -func ExtractTextFromHtml(s string) string { +// ExtractTextFromHTML returns a string with only the text version of the web page +func ExtractTextFromHTML(s string) string { ret := "" domDocTest := html.NewTokenizer(strings.NewReader(s)) previousStartTokenTest := domDocTest.Token() diff --git a/utils/misc.go b/utils/misc.go index fcb6f03..46cd169 100644 --- a/utils/misc.go +++ b/utils/misc.go @@ -5,6 +5,7 @@ import ( "os" ) +// IsFlagPassed returns true if the flag is present on the command line func IsFlagPassed(name string) bool { found := false flag.Visit(func(f *flag.Flag) { @@ -15,6 +16,7 @@ func IsFlagPassed(name string) bool { return found } +// FileExists returns true if the file is present on disk func FileExists(filename string) bool { info, err := os.Stat(filename) if os.IsNotExist(err) { @@ -23,6 +25,7 @@ func FileExists(filename string) bool { return !info.IsDir() } +// DirExists returns true if the directory is present on disk func DirExists(path string) bool { info, err := os.Stat(path) if os.IsNotExist(err) {