Repository: jolicode/elasticsearch-cheatsheet Branch: gh-pages Commit: a93b18938c53 Files: 8 Total size: 61.3 KB Directory structure: gitextract_vhv_1t45/ ├── CNAME ├── LICENSE ├── README.md ├── index.html ├── javascripts/ │ └── prism.js ├── semantic-UI/ │ ├── LICENSE │ └── themes/ │ └── default/ │ └── assets/ │ └── fonts/ │ └── icons.otf └── stylesheets/ └── prism.css ================================================ FILE CONTENTS ================================================ ================================================ FILE: CNAME ================================================ elasticsearch-cheatsheet.jolicode.com ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2016 JoliCode Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # Elasticsearch Cheatsheet for developpers https://elasticsearch-cheatsheet.jolicode.com/ # License MIT, see LICENSE file. ================================================ FILE: index.html ================================================ Elasticsearch Cheat Sheet for developers

🔎 Elasticsearch 1.x 2.x 5.x 6.x 7.x 8.x Cheatsheet 🔍

All the API endpoints and pro-tips you always forgot about in one place!
Built by developers for developers. Hosted on GitHub, contributions welcome.

Elasticsearch 1.7 is End Of Life. Consider upgrading. More information about supported versions.

Elasticsearch 2.4 is End Of Life. Consider upgrading. More information about supported versions.

Elasticsearch 5.6 is End Of Life. Consider upgrading. More information about supported versions.

Elasticsearch 6.8 is End Of Life. Consider upgrading. More information about supported versions.

Links

First thing, forget about your curl calls and install Sense please!

First thing, forget about your curl calls and install Kibana please!

Queries

There are two syntaxes for the basic queries: a simple one on the left, where you can't use any option, and an extended one on the right. Most of the beginner headache with the DSL come from this:

GET _search
{
  "query": {
    "match": {
      "FIELD": "TEXT"
    }
  }
}
to
GET _search
{
  "query": {
    "match": {
      "FIELD": {
        "query": "TEXT",
        "OPTION": "VALUE"
      }
    }
  }
}

Full search example with aggregation, highlight, filter...

GET /_search
{
  "query": {
    "filtered": {
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "title": "smith"
              }
            }
          ],
          "must_not": [
            {
              "match_phrase": {
                "title": "granny smith"
              }
            }
          ]
        }
      },
      "filter": {
        "bool": {
          "must_not": [
            {
              "missing": {
                "field": "title"
              }
            }
          ]
        }
      }
    }
  },
  "aggs": {
    "my_agg": {
      "terms": {
        "field": "user",
        "size": 10
      }
    }
  },
  "highlight": {
    "pre_tags" : ["<em>"],
    "post_tags" : ["</em>"],
    "fields": {
      "body" : {
        "number_of_fragments": 1,
        "fragment_size": 20
      },
      "title": {}
    }
  },
  "size": 20,
  "from": 100,
  "_source": ["title", "id"],
  "sort": [
    { "_id" : {"order" : "desc"}}
  ]
}
GET /_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "title": "smith"
          }
        }
      ],
      "must_not": [
        {
          "match_phrase": {
            "title": "granny smith"
          }
        }
      ],
      "filter": [
        {
          "exists": {
            "field": "title"
          }
        }
      ]
    }
  },
  "aggs": {
    "my_agg": {
      "terms": {
        "field": "user",
        "size": 10
      }
    }
  },
  "highlight": {
    "pre_tags": [
      "<em>"
    ],
    "post_tags": [
      "</em>"
    ],
    "fields": {
      "body": {
        "number_of_fragments": 1,
        "fragment_size": 20
      },
      "title": {}
    }
  },
  "size": 20,
  "from": 100,
  "_source": [
    "title",
    "id"
  ],
  "sort": [
    {
      "_id": {
        "order": "desc"
      }
    }
  ]
}

Control total hit count

Accept true, false or a fixed number, default to 10000.

GET /_search
{
  "track_total_hits": true,
  "query": {}
}

Common queries

"multi_match": {
  "query": "Elastic",
  "fields": ["user.*", "title^3"],
  "type": "best_fields"
}
"bool": {
  "must": [],
  "must_not": [],
  "filter": [],
  "should": [],
  "minimum_should_match" : 1
}
"bool": {
  "must": [],
  "must_not": [],
  "should": [],
  "minimum_should_match" : 1
}
"filtered": {
  "query": {
    "match_all": {}
  },
  "filter": {
    "range": {...}
  }
}
"range": {
  "age": {
    "gte": 10,
    "lte": 20,
    "boost": 2
  }
}

QueryString syntax

Search in the default _all field:

GET /_search?q=pony

Complex search with operator and exact phrase search with boost:

GET /_search?q=title:(joli OR code) AND author:"Damien Alexandre"^2

Search with wildcard and special queries:

GET /_search?q=_exists_:title OR title:singl? noneOrAnyChar*cter

Search with fuzzyness and range:

GET /_search?q=title:elastichurch~3 AND date:[2016-01-01 TO 2018-12-31]

Use in Query DSL (not recommended for user search):

GET /_search
{
  "query": {
    "query_string": {
      "default_field": "content",
      "query": "elastic AND (title:lucene OR title:solr)"
    }
  }
}

Search After - Pagination cursor

Search with a custom sort:

GET products/_search
{
    "size": 10,
    "sort": [
        {"date": "asc"},
        {"_id": "desc"}
    ]
}

On the next "page", pass the sort values from the last result:

GET product/_search
{
    "size": 10,
    "search_after": [1463538857, "654323"],
    "sort": [
        {"date": "asc"},
        {"_id": "desc"}
    ]
}

Indexes and mapping

Create an index with settings and mapping

PUT /my_index_name
{
  "settings": {
    "number_of_replicas": 1,
    "number_of_shards": 3,
    "analysis": {},
    "refresh_interval": "1s"
  },
  "mappings": {
    "my_type_name": {
      "dynamic": false,
      "properties": {
        "title": {
          "type": "string",
          "analyzer": "english"
        }
      }
    }
  }
}
PUT /my_index_name
{
  "settings": {
    "number_of_replicas": 1,
    "number_of_shards": 3,
    "analysis": {},
    "refresh_interval": "1s"
  },
  "mappings": {
    "my_type_name": {
      "dynamic": false,
      "properties": {
        "title": {
          "type": "text",
          "analyzer": "english"
        }
      }
    }
  }
}
PUT /my_index_name
{
  "settings": {
    "number_of_replicas": 1,
    "number_of_shards": 3,
    "analysis": {},
    "refresh_interval": "1s"
  },
  "mappings": {
    "dynamic": false,
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "english"
      }
    }
  }
}

Types are deprecated, you can only use one in Elasticsearch 6.

Update index settings dynamically

PUT /my_index_name/_settings
{
  "index": {
    "refresh_interval": "-1",
    "number_of_replicas": 0
  }
}

Update an index by adding a field to a type

PUT /my_index_name/_mapping/my_type_name
{
  "my_type_name": {
    "properties": {
      "tag": {
        "type": "string",
        "index": "not_analyzed"
      }
    }
  }
}
PUT /my_index_name/_mapping/my_type_name
{
  "my_type_name": {
    "properties": {
      "tag": {
        "type": "keyword"
      }
    }
  }
}
PUT /my_index_name/_mapping
{
  "properties": {
    "tag": {
      "type": "keyword"
    }
  }
}

Get the mapping and the settings

GET /my_index_name
GET /my_index_name/_mapping
GET /my_index_name/_settings

Create a document (auto-generated ID)

POST /my_index_name/my_type_name
{
  "title": "Elastic is funny",
  "tag": [
    "lucene"
  ]
}
POST /my_index_name/_doc
{
  "title": "Elastic is funny",
  "tag": [
    "lucene"
  ]
}

Get a document

GET /my_index_name/my_type_name/12abc
GET /my_index_name/_doc/12abc

Create or update a document

PUT /my_index_name/my_type_name/12abc
{
  "title": "Elastic is funny",
  "tag": [
    "lucene"
  ]
}
PUT /my_index_name/_doc/12abc
{
  "title": "Elastic is funny",
  "tag": [
    "lucene"
  ]
}

Delete a document

DELETE /my_index_name/my_type_name/12abc
DELETE /my_index_name/_doc/12abc

Open and close indexes to save memory and CPU

POST /my_index_name/_close
POST /my_index_name/_open

Remove and create aliases

POST /_aliases
{
  "actions": [
    {
      "remove": {
        "index": "my_index_name",
        "alias": "foo"
      }
    },
    {
      "add": {
        "index": "my_index_name",
        "alias": "bar",
        "filter" : { "term" : { "user" : "damien" } }
      }
    }
  ]
}

List aliases

GET /_aliases
GET /my_index_name/_alias/*
GET /*/_alias/*
GET /*/_alias/foo

Full custom analyzer declaration

PUT /english_example
{
  "settings": {
    "analysis": {
      "filter": {
        "english_stop": {
          "type":       "stop",
          "stopwords":  "_english_"
        },
        "english_stemmer": {
          "type":       "stemmer",
          "language":   "english"
        }
      },
      "analyzer": {
        "my_english": {
          "char_filter":  ["html_strip"],
          "tokenizer":  "standard",
          "filter": [
            "lowercase",
            "english_stop",
            "english_stemmer"
          ]
        }
      }
    }
  }
}

Create and list index warmer

Create a query that will be played on every new document:

PUT /my_index_name/_warmer/my_warmer
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "costly_aggs": {
      "terms": {
        "field": "title"
      }
    }
  }
}
GET /my_index_name/_warmer
GET /my_index_name/_warmer/*

Indices monitoring and information

GET /my_index_name/_stats
GET /my_index_name/_segments
GET /my_index_name/_recovery?pretty&human
GET /my_index_name/_warmer/*

Indices status and management

POST /my_index_name/_cache/clear
POST /my_index_name/_refresh
POST /my_index_name/_flush
POST /my_index_name/_optimize
POST /my_index_name/_forcemerge

Reindex API

Simple Reindex Operation

POST /_reindex
{
  "source": {
    "index": "test-index"
  },
  "dest": {
    "index": "test-index-new"
  }
}

Selective Reindex Operation

POST /_reindex
{
  "source": {
    "index": "test-index",
    "query": {
      "match": {
        "gender": "female"
      }
    }
  },
  "dest": {
    "index": "test-index-new",
    "type": "female"
  }
}

Debug and development

Queries

Get a detailed view of what a query do:

GET /blog/_validate/query?explain=true
{
  "query": {
    "match": {
      "title": "Smith"
    }
  }
}

Get an explanation about a document matching or not:

GET /blog/post/1/_explain
{
  "query": {
    "match": {
      "title": "Smith"
    }
  }
}
GET /blog/_explain/1
{
  "query": {
    "match": {
      "title": "Smith"
    }
  }
}

Analysis

Test how a content is tokenized in a field:

GET /blog/_analyze
{
  "field": "title",
  "text": "powerful"
}

Test analyzer token output by analyzer:

GET /blog/_analyze
{
  "analyzer": "english",
  "text": "powerful"
}

Slowlog

Lower the slowlog threshold to see all the search queries in the logs:

PUT /blog/_settings
{
  "index.search.slowlog.threshold.query.trace": "0s",
  "index.search.slowlog.level": "trace"
}

Go back to the default configuration:

PUT /blog/_settings
{
  "index.search.slowlog.threshold.query.trace": "500ms",
  "index.search.slowlog.level": "info"
}

Cluster management and plugins

Running with Docker

Elasticsearch:

docker network create elastic
docker run --rm -it --name "elastically_es" -e "discovery.type=single-node" --net elastic docker.elastic.co/elasticsearch/elasticsearch:8.1.2

Have a look at the output for password and enrollment token!

docker run --rm -it --name "elastically_es" -p 9200:9200 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.17.2
docker run -d --name "elastically_es" -p 9200:9200 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:6.8.6
docker run -d --name "elastically_es" -p 9200:9200 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:5.6.16

Kibana:

docker run --rm -it --name "elastically_kibana" --net elastic -p 5601:5601 docker.elastic.co/kibana/kibana:8.1.2
docker run -e "ELASTICSEARCH_HOSTS=http://127.0.0.1:9200/" --network host docker.elastic.co/kibana/kibana:7.17.2
docker run -e "ELASTICSEARCH_HOSTS=http://127.0.0.1:9200/" --network host docker.elastic.co/kibana/kibana:6.8.6
docker run -e "ELASTICSEARCH_HOSTS=http://127.0.0.1:9200/" --network host docker.elastic.co/kibana/kibana:5.6.16

Cluster and node information

GET /_cluster/health?pretty
GET /_cluster/health?wait_for_status=yellow&timeout=50s
GET /_cluster/state
GET /_cluster/stats?human&pretty
GET /_cluster/pending_tasks
GET /_nodes
GET /_nodes/stats
GET /_nodes/nodeId1,nodeId2/stats
GET /_shutdown 😱

Get the full reference of all the settings:

GET /_cluster/settings?include_defaults=true&flat_settings=true

Moving shards manually

Ask the index my_index_name shard 0 of node1 to go to node2:

POST /_cluster/reroute
{
  "commands": [
    {
      "move": {
        "index": "my_index_name",
        "shard": 0,
        "from_node": "node1",
        "to_node": "node2"
      }
    },
    {
      "allocate": {
        "index": "my_index_name",
        "shard": 1,
        "node": "node3"
      }
    }
  ]
}

Updating settings

Change dynamically the minimum number of nodes to allow a master election, both persistent or not:

PUT /_cluster/settings
{
  "persistent": {
    "discovery.zen.minimum_master_nodes": 3
  }
}
PUT /_cluster/settings
{
  "transient": {
    "discovery.zen.minimum_master_nodes": 2
  }
}

Disable shard allocation, useful before a rolling restart:

PUT /_cluster/settings
{
    "transient" : {
        "cluster.routing.allocation.enable" : "none"
    }
}
PUT /_cluster/settings
{
    "transient" : {
        "cluster.routing.allocation.enable" : "all"
    }
}

Snapshots and Restore

PUT /_snapshot/my_backup
{
  "type": "fs",
  "settings": {
    "location": "my_backup_location"
  }
}
PUT /_snapshot/my_backup/snapshot_a
{
  "indices": "index_1,index_2",
  "ignore_unavailable": "true",
  "include_global_state": false
}
POST /_snapshot/my_backup/snapshot_a/_restore
{
  "indices": "index_1,index_2",
  "ignore_unavailable": "true",
  "include_global_state": false,
  "rename_pattern": "index_(.+)",
  "rename_replacement": "restored_index_$1"
}

Most useful plugins

Site plugins are no longer supported, look at Kibana applications or other standalone app like Cerebro for basic management.

Kopf

Nice and easy user interface to manage Elasticsearch, with forms for a lots of API.

bin/plugin --install lmenezes/elasticsearch-kopf/1.0 bin/plugin install lmenezes/elasticsearch-kopf/2.0
Marvel

Official monitoring solution.

bin/plugin --install elasticsearch/marvel/1.3
Elasticsearch-HQ

Monitoring, Management, and statistics analysis.

bin/plugin --install royrusso/elasticsearch-HQ/v1.0.0 bin/plugin install royrusso/elasticsearch-HQ
Mapper-Attachments

Index file attachments in over a thousand formats (such as PPT, XLS, PDF) using the Apache text extraction library Tika.

bin/plugin --install elasticsearch/elasticsearch-mapper-attachments/2.7.1 bin/plugin install elasticsearch/elasticsearch-mapper-attachments
Analysis ICU

Adding useful tokenizer and token filters from the Unicode ICU library.

bin/plugin --install elasticsearch/elasticsearch-analysis-icu/2.7.0 bin/plugin install analysis-icu bin/elasticsearch-plugin install analysis-icu
AWS Cloud

Allow discovery and storage in Amazon cloud (EC2 and S3).

bin/plugin --install elasticsearch/elasticsearch-cloud-aws/2.7.1 bin/plugin install cloud-aws bin/elasticsearch-plugin install discovery-ec2 bin/elasticsearch-plugin install repository-s3
Azure Cloud

Allow discovery and storage in Microsoft Azure cloud.

bin/plugin --install elasticsearch/elasticsearch-cloud-azure/2.8.3 bin/plugin install cloud-azure bin/elasticsearch-plugin install discovery-azure-classic bin/elasticsearch-plugin install repository-azure

Plugins management

bin/plugin --url file:///path/to/plugin --install plugin-name
bin/plugin --remove [pluginname]
bin/plugin install file:///path/to/plugin
bin/plugin list
bin/plugin remove [pluginname]
bin/elasticsearch-plugin install file:///path/to/plugin
bin/elasticsearch-plugin list
bin/elasticsearch-plugin remove [pluginname]

Other information

Where to find the plugin binary?

RPM: /usr/share/elasticsearch/bin

Debian: /usr/share/elasticsearch/bin

What are the default ports?

Kibana: http://localhost:5601/.

Elasticsearch: http://localhost:9200/.

How to set the correct HEAP SIZE value?

The best value for a single purpose Elasticsearch server is about 50% of available RAM but under 32g.
Assuming Ubuntu / Debian server, you can change those files:

/etc/security/limits.conf

elasticsearch - nofile 65535
elasticsearch - memlock unlimited

/etc/default/elasticsearch (on CentOS/RH: /etc/sysconfig/elasticsearch)

ES_HEAP_SIZE=20g
MAX_OPEN_FILES=65535
MAX_LOCKED_MEMORY=unlimited

Useful settings to change in elasticsearch.yml

cluster.name: jolicluster
node.name: ${HOSTNAME}
plugin.mandatory: marvel-agent,analysis-icu,license
node.data: true
node.master: true
bootstrap.mlockall: true
action.auto_create_index: +aaa*,-bbb*,+ccc*,-*
cluster.name: jolicluster
node.name: ${HOSTNAME}
discovery.zen.ping.unicast.hosts: ["front01", "front02"]
discovery.zen.minimum_master_nodes: 2
network.host: _site_
network.bind_host: [_site_, _local_]
plugin.mandatory: analysis-icu, marvel-agent
node.data: true
node.master: true
bootstrap.mlockall: true
action.auto_create_index: +aaa*,-bbb*,+ccc*,-*
cluster.name: jolicluster
node.name: ${HOSTNAME}
discovery.zen.ping.unicast.hosts: ["front01", "front02"]
discovery.zen.minimum_master_nodes: 2
network.host: _site_
network.bind_host: [_site_, _local_]
plugin.mandatory: analysis-icu
node.data: true
node.master: true
bootstrap.memory_lock: true
action.auto_create_index: +aaa*,-bbb*,+ccc*,-*

# Disable X-Pack features
xpack.security.enabled: false
xpack.monitoring.enabled: false
xpack.ml.enabled: false
xpack.watcher.enabled: false
xpack.sql.enabled: false
xpack.graph.enabled: false

# Only for XPack plugin for ES <= 6.2
#xpack.reporting.enabled: false
cluster.name: jolicluster
node.name: ${HOSTNAME} # by default

network.host: [_local_, _site_]
plugin.mandatory: analysis-icu
node.data: true
node.master: true
node.ingest: true
bootstrap.memory_lock: true
action.auto_create_index: +aaa*,-bbb*,+ccc*,-*

discovery.seed_hosts:
  - 192.168.1.10:9300
  - 192.168.1.11
  - seeds.mydomain.com

# Needed for first cluster boot
cluster.initial_master_nodes:
  - 10.0.10.101
  - 10.0.10.102:9300
  - 10.0.10.102:9301
  - master-node-name

# Disable X-Pack features, choose wisely
xpack.ccr.enabled: false
xpack.data_frame.enabled: false
xpack.enrich.enabled: false
xpack.flattened.enabled: false
xpack.graph.enabled: false
xpack.ilm.enabled: false
xpack.logstash.enabled: false
xpack.ml.enabled: false
xpack.monitoring.enabled: false
xpack.rollup.enabled: false
xpack.security.enabled: false
xpack.slm.enabled: false
xpack.sql.enabled: false
xpack.transform.enabled: false
xpack.vectors.enabled: false
xpack.watcher.enabled: false
================================================ FILE: javascripts/prism.js ================================================ /* PrismJS 1.19.0 https://prismjs.com/download.html?#themes=prism-solarizedlight&languages=markup+clike+javascript+json+yaml&plugins=toolbar+copy-to-clipboard */ var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(u){var c=/\blang(?:uage)?-([\w-]+)\b/i,n=0,C={manual:u.Prism&&u.Prism.manual,disableWorkerMessageHandler:u.Prism&&u.Prism.disableWorkerMessageHandler,util:{encode:function(e){return e instanceof _?new _(e.type,C.util.encode(e.content),e.alias):Array.isArray(e)?e.map(C.util.encode):e.replace(/&/g,"&").replace(/e.length)return;if(!(k instanceof _)){if(h&&y!=n.length-1){if(c.lastIndex=v,!(O=c.exec(e)))break;for(var b=O.index+(f&&O[1]?O[1].length:0),w=O.index+O[0].length,A=y,P=v,x=n.length;A"+r.content+""},!u.document)return u.addEventListener&&(C.disableWorkerMessageHandler||u.addEventListener("message",function(e){var n=JSON.parse(e.data),r=n.language,t=n.code,a=n.immediateClose;u.postMessage(C.highlight(t,C.languages[r],r)),a&&u.close()},!1)),C;var e=C.util.currentScript();if(e&&(C.filename=e.src,e.hasAttribute("data-manual")&&(C.manual=!0)),!C.manual){function r(){C.manual||C.highlightAll()}var t=document.readyState;"loading"===t||"interactive"===t&&e&&e.defer?document.addEventListener("DOMContentLoaded",r):window.requestAnimationFrame?window.requestAnimationFrame(r):window.setTimeout(r,16)}return C}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); Prism.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:(?!)*\]\s*)?>/i,greedy:!0},cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/i,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/i,inside:{punctuation:[/^=/,{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))}),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var n={"included-cdata":{pattern://i,inside:s}};n["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var t={};t[a]={pattern:RegExp("(<__[\\s\\S]*?>)(?:\\s*|[\\s\\S])*?(?=<\\/__>)".replace(/__/g,a),"i"),lookbehind:!0,greedy:!0,inside:n},Prism.languages.insertBefore("markup","cdata",t)}}),Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup; Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(?:true|false)\b/,function:/\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}; Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],number:/\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,function:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,operator:/--|\+\+|\*\*=?|=>|&&|\|\||[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?[.?]?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=(?:\s|\/\*[\s\S]*?\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)?\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=>)/i,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\s*)\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.js=Prism.languages.javascript; Prism.languages.json={property:{pattern:/"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,greedy:!0},string:{pattern:/"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,greedy:!0},comment:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,number:/-?\d+\.?\d*(?:e[+-]?\d+)?/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:true|false)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}}; Prism.languages.yaml={scalar:{pattern:/([\-:]\s*(?:![^\s]+)?[ \t]*[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)[^\r\n]+(?:\2[^\r\n]+)*)/,lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:/(\s*(?:^|[:\-,[{\r\n?])[ \t]*(?:![^\s]+)?[ \t]*)[^\r\n{[\]},#\s]+?(?=\s*:\s)/,lookbehind:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)(?:\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?)?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?)(?=[ \t]*(?:$|,|]|}))/m,lookbehind:!0,alias:"number"},boolean:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)(?:true|false)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},null:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)(?:null|~)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},string:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)("|')(?:(?!\2)[^\\\r\n]|\\.)*\2(?=[ \t]*(?:$|,|]|}|\s*#))/m,lookbehind:!0,greedy:!0},number:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+\.?\d*|\.?\d+)(?:e[+-]?\d+)?|\.inf|\.nan)[ \t]*(?=$|,|]|})/im,lookbehind:!0},tag:/![^\s]+/,important:/[&*][\w]+/,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},Prism.languages.yml=Prism.languages.yaml; !function(){if("undefined"!=typeof self&&self.Prism&&self.document){var r=[],i={},a=function(){};Prism.plugins.toolbar={};var t=Prism.plugins.toolbar.registerButton=function(t,a){var e;e="function"==typeof a?a:function(t){var e;return"function"==typeof a.onClick?((e=document.createElement("button")).type="button",e.addEventListener("click",function(){a.onClick.call(this,t)})):"string"==typeof a.url?(e=document.createElement("a")).href=a.url:e=document.createElement("span"),a.className&&e.classList.add(a.className),e.textContent=a.text,e},t in i?console.warn('There is a button with the key "'+t+'" registered already.'):r.push(i[t]=e)},e=Prism.plugins.toolbar.hook=function(n){var t=n.element.parentNode;if(t&&/pre/i.test(t.nodeName)&&!t.parentNode.classList.contains("code-toolbar")){var e=document.createElement("div");e.classList.add("code-toolbar"),t.parentNode.insertBefore(e,t),e.appendChild(t);var o=document.createElement("div");o.classList.add("toolbar"),document.body.hasAttribute("data-toolbar-order")&&(r=document.body.getAttribute("data-toolbar-order").split(",").map(function(t){return i[t]||a})),r.forEach(function(t){var e=t(n);if(e){var a=document.createElement("div");a.classList.add("toolbar-item"),a.appendChild(e),o.appendChild(a)}}),e.appendChild(o)}};t("label",function(t){var e=t.element.parentNode;if(e&&/pre/i.test(e.nodeName)&&e.hasAttribute("data-label")){var a,n,o=e.getAttribute("data-label");try{n=document.querySelector("template#"+o)}catch(t){}return n?a=n.content:(e.hasAttribute("data-url")?(a=document.createElement("a")).href=e.getAttribute("data-url"):a=document.createElement("span"),a.textContent=o),a}}),Prism.hooks.add("complete",e)}}(); !function(){if("undefined"!=typeof self&&self.Prism&&self.document)if(Prism.plugins.toolbar){var r=window.ClipboardJS||void 0;r||"function"!=typeof require||(r=require("clipboard"));var i=[];if(!r){var o=document.createElement("script"),e=document.querySelector("head");o.onload=function(){if(r=window.ClipboardJS)for(;i.length;)i.pop()()},o.src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.0/clipboard.min.js",e.appendChild(o)}Prism.plugins.toolbar.registerButton("copy-to-clipboard",function(e){var t=document.createElement("button");return t.textContent="Copy",r?o():i.push(o),t;function o(){var o=new r(t,{text:function(){return e.code}});o.on("success",function(){t.textContent="Copied!",n()}),o.on("error",function(){t.textContent="Press Ctrl+C to copy",n()})}function n(){setTimeout(function(){t.textContent="Copy"},5e3)}})}else console.warn("Copy to Clipboard plugin loaded before Toolbar plugin.")}(); ================================================ FILE: semantic-UI/LICENSE ================================================ The MIT License (MIT) Copyright (c) 2015 Semantic Org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: stylesheets/prism.css ================================================ /* PrismJS 1.19.0 https://prismjs.com/download.html?#themes=prism-solarizedlight&languages=markup+clike+javascript+json+yaml&plugins=toolbar+copy-to-clipboard */ /* Solarized Color Schemes originally by Ethan Schoonover http://ethanschoonover.com/solarized Ported for PrismJS by Hector Matos Website: https://krakendev.io Twitter Handle: https://twitter.com/allonsykraken) */ /* SOLARIZED HEX --------- ------- base03 #002b36 base02 #073642 base01 #586e75 base00 #657b83 base0 #839496 base1 #93a1a1 base2 #eee8d5 base3 #fdf6e3 yellow #b58900 orange #cb4b16 red #dc322f magenta #d33682 violet #6c71c4 blue #268bd2 cyan #2aa198 green #859900 */ code[class*="language-"], pre[class*="language-"] { color: #657b83; /* base00 */ font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; text-align: left; white-space: pre; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; -moz-tab-size: 4; -o-tab-size: 4; tab-size: 4; -webkit-hyphens: none; -moz-hyphens: none; -ms-hyphens: none; hyphens: none; } pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { background: #073642; /* base02 */ } pre[class*="language-"]::selection, pre[class*="language-"] ::selection, code[class*="language-"]::selection, code[class*="language-"] ::selection { background: #073642; /* base02 */ } /* Code blocks */ pre[class*="language-"] { padding: 1em; margin: .5em 0; overflow: auto; border-radius: 0.3em; } :not(pre) > code[class*="language-"], pre[class*="language-"] { background-color: #fdf6e3; /* base3 */ } /* Inline code */ :not(pre) > code[class*="language-"] { padding: .1em; border-radius: .3em; } .token.comment, .token.prolog, .token.doctype, .token.cdata { color: #93a1a1; /* base1 */ } .token.punctuation { color: #586e75; /* base01 */ } .token.namespace { opacity: .7; } .token.property, .token.tag, .token.boolean, .token.number, .token.constant, .token.symbol, .token.deleted { color: #268bd2; /* blue */ } .token.selector, .token.attr-name, .token.string, .token.char, .token.builtin, .token.url, .token.inserted { color: #2aa198; /* cyan */ } .token.entity { color: #657b83; /* base00 */ background: #eee8d5; /* base2 */ } .token.atrule, .token.attr-value, .token.keyword { color: #859900; /* green */ } .token.function, .token.class-name { color: #b58900; /* yellow */ } .token.regex, .token.important, .token.variable { color: #cb4b16; /* orange */ } .token.important, .token.bold { font-weight: bold; } .token.italic { font-style: italic; } .token.entity { cursor: help; } div.code-toolbar { position: relative; } div.code-toolbar > .toolbar { position: absolute; top: .3em; right: .2em; transition: opacity 0.3s ease-in-out; opacity: 0; } div.code-toolbar:hover > .toolbar { opacity: 1; } /* Separate line b/c rules are thrown out if selector is invalid. IE11 and old Edge versions don't support :focus-within. */ div.code-toolbar:focus-within > .toolbar { opacity: 1; } div.code-toolbar > .toolbar .toolbar-item { display: inline-block; } div.code-toolbar > .toolbar a { cursor: pointer; } div.code-toolbar > .toolbar button { background: none; border: 0; color: inherit; font: inherit; line-height: normal; overflow: visible; padding: 0; -webkit-user-select: none; /* for button */ -moz-user-select: none; -ms-user-select: none; } div.code-toolbar > .toolbar a, div.code-toolbar > .toolbar button, div.code-toolbar > .toolbar span { color: #bbb; font-size: .8em; padding: 0 .5em; background: #f5f2f0; background: rgba(224, 224, 224, 0.2); box-shadow: 0 2px 0 0 rgba(0,0,0,0.2); border-radius: .5em; } div.code-toolbar > .toolbar a:hover, div.code-toolbar > .toolbar a:focus, div.code-toolbar > .toolbar button:hover, div.code-toolbar > .toolbar button:focus, div.code-toolbar > .toolbar span:hover, div.code-toolbar > .toolbar span:focus { color: inherit; text-decoration: none; }