├── .gitignore
├── favicon.ico
├── docs
├── broken.png
├── history.png
├── autocomplete.png
├── requestformat.png
└── syntaxhighlighting.png
├── icons
├── logo128.png
├── logo16.png
├── logo19.png
├── logo38.png
└── logo48.png
├── package.sh
├── lib
├── font-awesome
│ └── font
│ │ ├── FontAwesome.otf
│ │ ├── fontawesome-webfont.eot
│ │ ├── fontawesome-webfont.ttf
│ │ └── fontawesome-webfont.woff
├── bootstrap
│ ├── img
│ │ ├── glyphicons-halflings.png
│ │ └── glyphicons-halflings-white.png
│ └── js
│ │ └── bootstrap.min.js
├── jqueryui
│ └── jquery-ui-1.9.2.custom.min.css
├── src-noconflict
│ ├── theme-monokai.js
│ └── mode-json.js
└── moment.min.js
├── src
├── background.js
├── curl.js
├── kb.js
├── history.js
├── mappings.js
├── utils.js
└── base.js
├── .travis.yml
├── README.md
├── tests
├── src
│ ├── autocomplete_tests.js
│ ├── kb_tests.js
│ ├── curl_tests.js
│ ├── utils_tests.js
│ ├── mapping_tests.js
│ └── tokenization_tests.js
├── index.html
├── phantomjs.runner.js
└── lib
│ └── qunit-1.10.0.css
├── kb
├── globals.js
├── templates.js
├── warmers.js
├── misc.js
├── aliases.js
├── cluster.js
├── indices.js
├── settings.js
├── search.js
├── facets.js
├── mappings.js
├── filter.js
└── query.js
├── manifest.json
├── welcome.html
├── sense.css
└── index.html
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 |
--------------------------------------------------------------------------------
/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bleskes/sense_old/HEAD/favicon.ico
--------------------------------------------------------------------------------
/docs/broken.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bleskes/sense_old/HEAD/docs/broken.png
--------------------------------------------------------------------------------
/docs/history.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bleskes/sense_old/HEAD/docs/history.png
--------------------------------------------------------------------------------
/icons/logo128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bleskes/sense_old/HEAD/icons/logo128.png
--------------------------------------------------------------------------------
/icons/logo16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bleskes/sense_old/HEAD/icons/logo16.png
--------------------------------------------------------------------------------
/icons/logo19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bleskes/sense_old/HEAD/icons/logo19.png
--------------------------------------------------------------------------------
/icons/logo38.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bleskes/sense_old/HEAD/icons/logo38.png
--------------------------------------------------------------------------------
/icons/logo48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bleskes/sense_old/HEAD/icons/logo48.png
--------------------------------------------------------------------------------
/docs/autocomplete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bleskes/sense_old/HEAD/docs/autocomplete.png
--------------------------------------------------------------------------------
/docs/requestformat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bleskes/sense_old/HEAD/docs/requestformat.png
--------------------------------------------------------------------------------
/package.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | zip -r "$1" icons kb lib src favicon.ico *.html manifest.json sense.css
3 |
--------------------------------------------------------------------------------
/docs/syntaxhighlighting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bleskes/sense_old/HEAD/docs/syntaxhighlighting.png
--------------------------------------------------------------------------------
/lib/font-awesome/font/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bleskes/sense_old/HEAD/lib/font-awesome/font/FontAwesome.otf
--------------------------------------------------------------------------------
/lib/bootstrap/img/glyphicons-halflings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bleskes/sense_old/HEAD/lib/bootstrap/img/glyphicons-halflings.png
--------------------------------------------------------------------------------
/lib/font-awesome/font/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bleskes/sense_old/HEAD/lib/font-awesome/font/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/lib/font-awesome/font/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bleskes/sense_old/HEAD/lib/font-awesome/font/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/lib/font-awesome/font/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bleskes/sense_old/HEAD/lib/font-awesome/font/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/lib/bootstrap/img/glyphicons-halflings-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bleskes/sense_old/HEAD/lib/bootstrap/img/glyphicons-halflings-white.png
--------------------------------------------------------------------------------
/src/background.js:
--------------------------------------------------------------------------------
1 | chrome.browserAction.onClicked.addListener(function (tab) {
2 | chrome.tabs.create({'url': chrome.extension.getURL('index.html')}, function (tab) {
3 | });
4 | });
5 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 | python:
3 | - "2.7"
4 | before_script:
5 | - python -m SimpleHTTPServer &
6 | - sleep 3
7 |
8 | script: phantomjs tests/phantomjs.runner.js http://localhost:8000/tests/
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | Sense is now part of Marvel
3 | =====
4 |
5 | The development of Sense has moved into Elasticsearch Marvel, you can find it here: http://www.elasticsearch.org/overview/marvel/
6 |
7 | If you have any question or find an issue, feel free to post on the elasticsearch user group: http://groups.google.com/forum/#!forum/elasticsearch
8 |
--------------------------------------------------------------------------------
/tests/src/autocomplete_tests.js:
--------------------------------------------------------------------------------
1 | var global = window;
2 |
3 | module("Autocomplete", {
4 | setup: function () {
5 | if (!global.sense)
6 | global.sense = {};
7 | var sense = global.sense;
8 | sense.tests = {};
9 | },
10 |
11 | teardown: function () {
12 | sense.tests = {};
13 | }
14 | });
15 |
--------------------------------------------------------------------------------
/kb/globals.js:
--------------------------------------------------------------------------------
1 | sense.kb.addGlobalAutocompleteRules("highlight", {
2 | pre_tags: {}, post_tags: {}, tags_schema: {},
3 | fields: { "$FIELD$": { "fragment_size": {}, "number_of_fragments": {} }}
4 | }
5 | );
6 |
7 | // only used with scope links as there is no common name for scripts
8 | sense.kb.addGlobalAutocompleteRules("SCRIPT_ENV", {
9 | __template: { "script": ""},
10 | script: "",
11 | lang: "",
12 | params: {}
13 | }
14 | );
15 |
--------------------------------------------------------------------------------
/kb/templates.js:
--------------------------------------------------------------------------------
1 | sense.kb.addEndpointDescription('_template', {
2 | match: /\/?_template/,
3 | def_method: "PUT",
4 | methods: ["GET", "PUT", "DELETE"],
5 | endpoint_autocomplete: [
6 | "_template/TEMPLATE_ID"
7 | ],
8 | indices_mode: "none",
9 | types_mode: "none",
10 | doc_id_mode: "none",
11 |
12 | data_autocomplete_rules: {
13 | template: "index*",
14 | warmers: { __scope_link: "_warmer" },
15 | mappings: {},
16 | settings: {}
17 | }
18 | });
--------------------------------------------------------------------------------
/kb/warmers.js:
--------------------------------------------------------------------------------
1 | sense.kb.addEndpointDescription('_warmer', {
2 | match: /_warmer/,
3 | def_method: "PUT",
4 | methods: ["GET", "PUT", "DELETE"],
5 | endpoint_autocomplete: [
6 | "_warmer", "_warmer/WARMER_ID"
7 | ],
8 | indices_mode: "required_multi",
9 | types_mode: "none",
10 | doc_id_mode: "none",
11 | data_autocomplete_rules: {
12 | query: {
13 | // populated by a global rule
14 | },
15 | facets: {
16 | // populated by a global rule
17 | }
18 | }
19 | });
--------------------------------------------------------------------------------
/kb/misc.js:
--------------------------------------------------------------------------------
1 | sense.kb.addEndpointDescription('_stats', {
2 | methods: ["GET"],
3 | endpoint_autocomplete: ['_stats'],
4 | indices_mode: "multi",
5 | types_mode: "none",
6 | doc_id_mode: "none"
7 | });
8 |
9 | sense.kb.addEndpointDescription('_cache/clear', {
10 | methods: ["GET"],
11 | endpoint_autocomplete: ['_cache/clear'],
12 | indices_mode: "multi",
13 | types_mode: "none",
14 | doc_id_mode: "none"
15 | });
16 | sense.kb.addEndpointDescription('_status', {
17 | methods: ["GET"],
18 | indices_mode: "multi",
19 | types_mode: "none",
20 | doc_id_mode: "none",
21 | endpoint_autocomplete: ['_status']
22 | });
23 |
24 |
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest_version": 2,
3 |
4 | "name": "Sense (Beta)",
5 | "description": "A JSON aware developer console to ElasticSearch.",
6 | "version": "0.9.0",
7 |
8 | "icons": {
9 | "16": "icons/logo16.png",
10 | "48": "icons/logo48.png",
11 | "128": "icons/logo128.png"
12 | },
13 |
14 | "permissions": [
15 | "https://*/",
16 | "http://*/",
17 | "tabs",
18 | "clipboardWrite"
19 | ],
20 | "browser_action": {
21 | "default_icon": {
22 | "19": "icons/logo19.png",
23 | "38": "icons/logo38.png"
24 | }
25 | },
26 | "background": {
27 | "scripts": ["src/background.js"]
28 | },
29 | "content_security_policy": "script-src 'self' https://ssl.google-analytics.com; object-src 'self'"
30 | }
--------------------------------------------------------------------------------
/kb/aliases.js:
--------------------------------------------------------------------------------
1 | sense.kb.addEndpointDescription('_aliases', {
2 | match: /_aliases/,
3 | def_method: "GET",
4 | methods: ["GET", "POST"],
5 | endpoint_autocomplete: [
6 | "_aliases"
7 | ],
8 | indices_mode: "multi",
9 | types_mode: "none",
10 | doc_id_mode: "none",
11 | data_autocomplete_rules: {
12 | "actions": {
13 | __template: [
14 | { "add": { "index": "test1", "alias": "alias1" } }
15 | ],
16 | __any_of: [
17 | {
18 | add: {
19 | index: "$INDEX$",
20 | alias: "",
21 | filter: {},
22 | routing: "1",
23 | search_routing: "1,2",
24 | index_routing: "1"
25 | },
26 | remove: {
27 | index: "",
28 | alias: ""
29 | }
30 | }
31 | ]
32 | }
33 | }
34 | });
--------------------------------------------------------------------------------
/kb/cluster.js:
--------------------------------------------------------------------------------
1 | sense.kb.addEndpointDescription('_cluster/nodes/stats', {
2 | methods: ["GET"],
3 | indices_mode: "none",
4 | types_mode: "none"
5 | });
6 | sense.kb.addEndpointDescription('_cluster/state', {
7 | methods: ["GET"],
8 | endpoint_autocomplete: ['_cluster/state'],
9 | indices_mode: "none",
10 | types_mode: "none"
11 | });
12 |
13 | sense.kb.addEndpointDescription('_cluster/health', {
14 | methods: ["GET"],
15 | endpoint_autocomplete: ['_cluster/health'],
16 | indices_mode: "none",
17 | types_mode: "none"
18 | });
19 |
20 | sense.kb.addEndpointDescription('_cluster/settings', {
21 | methods: ["GET", "PUT"],
22 | endpoint_autocomplete: ['_cluster/settings'],
23 | indices_mode: "none",
24 | types_mode: "none",
25 | data_autocomplete_rules: {
26 | persistent: {
27 | "routing.allocation.same_shard.host" : { __one_of: [ false, true ]}
28 | },
29 |
30 | transient: {
31 | __scope_link: ".persistent"
32 | }
33 | }
34 | });
35 |
--------------------------------------------------------------------------------
/kb/indices.js:
--------------------------------------------------------------------------------
1 | sense.kb.addEndpointDescription('_refresh', {
2 | def_method: "POST",
3 | methods: ["POST"],
4 | endpoint_autocomplete: [
5 | "_refresh"
6 | ],
7 | indices_mode: "multi"
8 | });
9 |
10 | sense.kb.addEndpointDescription('_stats', {
11 | def_method: "GET",
12 | methods: ["GET"],
13 | endpoint_autocomplete: [
14 | "_stats"
15 | ],
16 | indices_mode: "multi"
17 | });
18 |
19 | sense.kb.addEndpointDescription('_segments', {
20 | def_method: "GET",
21 | methods: ["GET"],
22 | endpoint_autocomplete: [
23 | "_segments"
24 | ],
25 | indices_mode: "multi"
26 | });
27 |
28 | sense.kb.addEndpointDescription('__create_index__', {
29 | methods: ["PUT", "DELETE"],
30 | indices_mode: "single",
31 | types_mode: "none",
32 | match: "^/?$",
33 | endpoint_autocomplete: [
34 | ""
35 | ],
36 | data_autocomplete_rules: {
37 | mappings: {
38 | __scope_link: "_mapping"
39 | },
40 | settings: {
41 | __scope_link: "_settings.index"
42 | }
43 | }
44 |
45 |
46 |
47 | });
--------------------------------------------------------------------------------
/welcome.html:
--------------------------------------------------------------------------------
1 |
Quick intro to the UI
2 |
3 | Sense is split into two panes: an editor pane (white) and a response pane (black).
4 | Use the editor to type requests and submit them to Elasticsearch. The results will be displayed in
5 | the response pane on the right side.
6 |
7 |
8 | Sense understands requests in a compact format, similar to cURL:
9 |
10 |
11 | While typing a request, Sense will make suggestions which you can than accept by hitting Enter/Tab.
12 | These suggestions are made based on the request structure as well as your indices and types.
13 |
14 |
15 |
16 | A few quick tips, while I have your attention
17 |
18 | Submit requests to ES using the green triangle button.
19 | Use the wrench menu for other useful things.
20 | You can paste requests in cURL format and they will be translated to the Sense syntax.
21 | You can resize the editor and output panes by dragging the separator between them.
22 | Study the keyboard shortcuts under the Help button. Good stuff in there!
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/kb/settings.js:
--------------------------------------------------------------------------------
1 | sense.kb.addEndpointDescription('_settings', {
2 | match: /_settings/,
3 | methods: ["GET", "PUT"],
4 | endpoint_autocomplete: ['_settings'],
5 | indices_mode: "multi",
6 | types_mode: "none",
7 | doc_id_mode: "none",
8 | data_autocomplete_rules: {
9 | index: {
10 | refresh_interval: "1s",
11 | number_of_replicas: 1,
12 | "blocks.read_only": { __one_of: [ false, true ]},
13 | "blocks.read": { __one_of: [ true, false ]},
14 | "blocks.write": { __one_of: [ true, false ]},
15 | "blocks.metadata": { __one_of: [ true, false] },
16 | term_index_interval: 32,
17 | term_index_divisor: 1,
18 | "translog.flush_threshold_ops": 5000,
19 | "translog.flush_threshold_size": "200mb",
20 | "translog.flush_threshold_period": "30m",
21 | "translog.disable_flush": { __one_of: [ true, false ]},
22 | "cache.filter.max_size": "2gb",
23 | "cache.filter.expire": "2h",
24 | "gateway.snapshot_interval": "10s",
25 | routing: {
26 | allocation: {
27 | include: { tag: "" },
28 | exclude: { tag: ""},
29 | require: { tag: ""},
30 | total_shards_per_node: -1
31 | }
32 | },
33 | "recovery.initial_shards": { __one_of: ["quorum", "quorum-1", "half", "full", "full-1" ]},
34 | "ttl.disable_purge": { __one_of: [ true, false ]},
35 | analysis: {
36 | analyzer: {},
37 | tokenizer: {},
38 | filter: {},
39 | char_filter: {}
40 | }
41 |
42 |
43 | }
44 | }
45 | });
46 |
--------------------------------------------------------------------------------
/kb/search.js:
--------------------------------------------------------------------------------
1 | sense.kb.addEndpointDescription('_search', {
2 | def_method: "POST",
3 | methods: ["GET", "POST"],
4 | endpoint_autocomplete: [
5 | "_search"
6 | ],
7 | indices_mode: "multi",
8 | types_mode: "multi",
9 | doc_id_mode: "none",
10 | data_autocomplete_rules: {
11 | query: {
12 | // populated by a global rule
13 | },
14 | facets: {
15 | __template: {
16 | "NAME": {
17 | "TYPE": {
18 | }
19 | }
20 | }
21 | // populated by a global rule
22 | },
23 | filter: {
24 | // added by global rules.
25 | },
26 | size: { __template: 20 },
27 | from: {},
28 | sort: {
29 | __template: [
30 | { "FIELD": { "order": "desc"} }
31 | ],
32 | __any_of: [
33 | {
34 | "$FIELD$": {
35 | "order": { __one_of: ["desc", "asc"]}
36 | }
37 | },
38 | "$FIELD$",
39 | "_score"
40 | ]
41 | },
42 | search_type: {},
43 | fields: [ "$FIELD$" ],
44 | script_fields: {
45 | __template: { "FIELD": {
46 | "script": ""
47 | }},
48 | "*": {
49 | __scope_link: "GLOBAL.SCRIPT_ENV"
50 | }
51 | },
52 | partial_fields: {
53 | __template: {
54 | "NAME": { include: [] }
55 | },
56 | "*": {
57 | include: [],
58 | exclude: []
59 | }
60 | },
61 | highlight: {
62 | // populated by a global rule
63 | },
64 | explain: { __one_of: [ true, false ]},
65 | stats: [ "" ]
66 |
67 | }
68 | });
--------------------------------------------------------------------------------
/tests/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Sense unittests
6 |
7 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/lib/jqueryui/jquery-ui-1.9.2.custom.min.css:
--------------------------------------------------------------------------------
1 | /*! jQuery UI - v1.9.2 - 2012-12-17
2 | * http://jqueryui.com
3 | * Includes: jquery.ui.core.css, jquery.ui.autocomplete.css, jquery.ui.menu.css
4 | * Copyright (c) 2012 jQuery Foundation and other contributors Licensed MIT */
5 |
6 | .ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{zoom:1}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:absolute;top:0;left:0;width:100%;height:100%}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}* html .ui-autocomplete{width:1px}.ui-menu{list-style:none;padding:2px;margin:0;display:block;outline:none}.ui-menu .ui-menu{margin-top:-3px;position:absolute}.ui-menu .ui-menu-item{margin:0;padding:0;zoom:1;width:100%}.ui-menu .ui-menu-divider{margin:5px -2px 5px -2px;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-menu-item a{text-decoration:none;display:block;padding:2px .4em;line-height:1.5;zoom:1;font-weight:normal}.ui-menu .ui-menu-item a.ui-state-focus,.ui-menu .ui-menu-item a.ui-state-active{font-weight:normal;margin:-1px}.ui-menu .ui-state-disabled{font-weight:normal;margin:.4em 0 .2em;line-height:1.5}.ui-menu .ui-state-disabled a{cursor:default}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item a{position:relative;padding-left:2em}.ui-menu .ui-icon{position:absolute;top:.2em;left:.2em}.ui-menu .ui-menu-icon{position:static;float:right}
--------------------------------------------------------------------------------
/src/curl.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | var global = window;
3 | if (!global.sense)
4 | global.sense = {};
5 |
6 | function detectCURL(text) {
7 | // returns true if text matches a curl request
8 | if (!text) return false;
9 | return text.match(/^\s*?curl\s+(-X[A-Z]+)?\s*['"]?.*?['"]?(\s*$|\s+?-d\s*?['"])/);
10 |
11 | }
12 |
13 | function parseCURL(text) {
14 | var matches = text.match(/^\s*?curl\s+(?:-s\s+)?(-X\s*[A-Z]+)?\s*/);
15 | var ret = {
16 | method: "",
17 | server: "",
18 | endpoint: "",
19 | data: ""
20 | };
21 | if (matches[1]) {
22 | ret.method = matches[1].substring(2).trim(); // strip -X
23 | }
24 | text = text.substring(matches[0].length); // strip everything so far.
25 | if (text.length == 0) return ret;
26 | if (text[0] == '"') {
27 | matches = text.match(/^"([^"]*)"/);
28 | }
29 | else if (text[0] == "'") {
30 | matches = text.match(/^'([^']*)'/);
31 | }
32 | else {
33 | matches = text.match(/^(\S*)/);
34 | }
35 |
36 | if (!matches) return ret;
37 | var url = matches[1];
38 |
39 | if (!url.match(/:\/\//)) url = "http://" + url; // inject http as curl does
40 |
41 | var urlAnchor = document.createElement("a");
42 | urlAnchor.href = url;
43 |
44 | ret.server = (urlAnchor.protocol || "http") + "//" + urlAnchor.hostname;
45 | if (urlAnchor.port && urlAnchor.port != 0) ret.server += ":" + urlAnchor.port;
46 | ret.url = (urlAnchor.pathname || "") + (urlAnchor.search || "");
47 |
48 | text = text.substring(matches[0].length);
49 |
50 | // now search for -d
51 | matches = text.match(/.*-d\s*?'/);
52 | if (matches) {
53 | ret.data = text.substring(matches[0].length).replace(/'\s*$/, '');
54 | }
55 | else {
56 | matches = text.match(/.*-d\s*?"/);
57 | if (matches) {
58 | ret.data = text.substring(matches[0].length).replace(/"\s*$/, '');
59 | ret.data = ret.data.replace(/\\(.)/gi, "$1");
60 | }
61 | }
62 |
63 | if (ret.data) {
64 | ret.data = ret.data.trim();
65 | }
66 |
67 | return ret;
68 | }
69 |
70 |
71 | global.sense.curl = {};
72 | global.sense.curl.parseCURL = parseCURL;
73 | global.sense.curl.detectCURL = detectCURL;
74 |
75 | })();
76 |
--------------------------------------------------------------------------------
/kb/facets.js:
--------------------------------------------------------------------------------
1 | sense.kb.addGlobalAutocompleteRules("facets", {
2 | "*": {
3 | terms: {
4 | __template: {
5 | field: "FIELD",
6 | size: 10
7 | },
8 | field: "$FIELD$",
9 | fields: ["$FIELD$"],
10 | size: 10,
11 | script: "",
12 | script_field: "",
13 | order: { __one_of: ["count", "term", "reverse_count", "reverse_term"]},
14 | all_terms: { __one_of: [false, true]},
15 | exclude: ["TERM"],
16 | regex: "",
17 | regex_flags: ""
18 | },
19 | range: {
20 | __template: {
21 | field: "FIELD",
22 | ranges: [
23 | { "to": 50 },
24 | { "from": 20, "to": 70 },
25 | { "from": 70, "to": 120 },
26 | { "from": 150 }
27 | ]
28 | },
29 | field: "$FIELD$",
30 | ranges: [
31 | { to: 10, from: 20}
32 | ]
33 | },
34 | histogram: {
35 | __template: {
36 | field: "FIELD", interval: 100
37 | },
38 | field: "$FIELD$",
39 | interval: 100,
40 | time_interval: "1.5h",
41 | key_field: "$FIELD$",
42 | value_field: "$FIELD$",
43 | key_script: "",
44 | value_script: "",
45 | params: {}
46 | },
47 | date_histogram: {
48 | __template: {
49 | field: "FIELD",
50 | "interval": "day"
51 | },
52 | field: "$FIELD$",
53 | interval: { __one_of: ["year", "quarter", "month", "week", "day", "hour", "minute", "1h", "1d", "1w"]},
54 | post_zone: -1,
55 | pre_zone: -1,
56 | factor: 1000,
57 | pre_offset: "1d",
58 | post_offset: "1d",
59 | key_field: "$FIELD$",
60 | value_field: "$FIELD$",
61 | value_script: ""
62 | },
63 | filter: {
64 | },
65 | query: {
66 | },
67 | facet_filter: {
68 | __scope_link: "GLOBAL.filter"
69 | },
70 | statistical: {
71 | __template: {
72 | field: "FIELD"
73 | },
74 | field: "$FIELD$",
75 | fields: ["$FIELD$"],
76 | script: ""
77 | },
78 | terms_stats: {
79 | __template: {
80 | key_field: "FIELD",
81 | value_field: "FIELD"
82 | },
83 | key_field: "$FIELD$",
84 | value_field: "$FIELD$",
85 | value_script: "",
86 | size: 10,
87 | order: {__one_of: ["count", "term", "reverse_term", "reverse_count", "total", "reverse_total",
88 | "min", "reverse_min", "max", "reverse_max", "mean", "reverse_mean"]}
89 | }
90 | }
91 | }
92 | );
93 |
--------------------------------------------------------------------------------
/tests/src/kb_tests.js:
--------------------------------------------------------------------------------
1 | var global = window;
2 |
3 | module("Knowledge base", {
4 | setup: function () {
5 | var sense = global.sense;
6 | sense.mappings.clear();
7 | sense.tests = {};
8 | },
9 |
10 | teardown: function () {
11 | sense.tests = {};
12 | }
13 | });
14 |
15 |
16 | test("Index mode filters", function () {
17 | global.sense.mappings.clear();
18 | global.sense.kb.clear();
19 | global.sense.kb.addEndpointDescription("_multi_indices", {
20 | indices_mode: "multi"
21 | });
22 | global.sense.kb.addEndpointDescription("_one_or_more_indices", {
23 | indices_mode: "required_multi"
24 | });
25 | global.sense.kb.addEndpointDescription("_single_index", {
26 | match: "_single_index",
27 | endpoint_autocomplete: [
28 | "_single_index"
29 | ],
30 | indices_mode: "single"
31 | });
32 | global.sense.kb.addEndpointDescription("_no_index", {
33 | indices_mode: "none"
34 | });
35 |
36 | deepEqual(global.sense.kb.getEndpointAutocomplete([], [], null).sort(), ["_multi_indices", "_no_index" ]);
37 | deepEqual(global.sense.kb.getEndpointAutocomplete(["index"], [], null).sort(), ["_multi_indices", "_one_or_more_indices", "_single_index"]);
38 | deepEqual(global.sense.kb.getEndpointAutocomplete(["index1", "index2"], [], null).sort(), ["_multi_indices", "_one_or_more_indices"]);
39 | deepEqual(global.sense.kb.getEndpointAutocomplete(["index1", "index2"], ["type"], null).sort(), ["_multi_indices", "_one_or_more_indices"]);
40 | });
41 |
42 | test("Type mode filters", function () {
43 | global.sense.mappings.clear();
44 | global.sense.kb.clear();
45 | global.sense.kb.addEndpointDescription("_multi_types", {
46 | indices_mode: "single",
47 | types_mode: "multi"
48 | });
49 | global.sense.kb.addEndpointDescription("_single_type", {
50 | endpoint_autocomplete: [
51 | "_single_type"
52 | ],
53 | indices_mode: "single",
54 | types_mode: "single"
55 | });
56 | global.sense.kb.addEndpointDescription("_no_types", {
57 | indices_mode: "single",
58 | types_mode: "none"
59 |
60 | });
61 |
62 | deepEqual(global.sense.kb.getEndpointAutocomplete(["index"], [], null).sort(), ["_multi_types", "_no_types" ]);
63 | deepEqual(global.sense.kb.getEndpointAutocomplete(["index"], ["type"], null).sort(), ["_multi_types", "_single_type"]);
64 | deepEqual(global.sense.kb.getEndpointAutocomplete(["index"], ["type", "type1"], null).sort(), ["_multi_types"]);
65 | });
66 |
67 | test("Id mode filters", function () {
68 | global.sense.kb.clear();
69 | global.sense.kb.addEndpointDescription("_single_id", {
70 | indices_mode: "single",
71 | types_mode: "single",
72 | doc_id_mode: "required_single"
73 | });
74 | global.sense.kb.addEndpointDescription("_no_id", {
75 | indices_mode: "single",
76 | types_mode: "single",
77 | doc_id_mode: "none"
78 |
79 | });
80 |
81 | deepEqual(global.sense.kb.getEndpointAutocomplete(["index"], ["type"], null).sort(), ["_no_id"].sort());
82 | deepEqual(global.sense.kb.getEndpointAutocomplete(["index"], ["type"], "123").sort(), ["_single_id"].sort());
83 | });
84 |
85 | test("Get active scheme by doc id", function () {
86 | global.sense.kb.clear();
87 | global.sense.kb.addEndpointDescription("_single_id", {
88 | match: ".*",
89 | indices_mode: "single",
90 | types_mode: "single",
91 | doc_id_mode: "required_single"
92 | });
93 | global.sense.kb.addEndpointDescription("_no_id", {
94 | match: ".*",
95 | indices_mode: "single",
96 | types_mode: "single",
97 | doc_id_mode: "none"
98 |
99 | });
100 |
101 | deepEqual(global.sense.kb.getEndpointDescriptionByPath("bla", ["index"], ["type"], null).doc_id_mode, "none");
102 | deepEqual(global.sense.kb.getEndpointDescriptionByPath("bla", ["index"], ["type"], "123").doc_id_mode, "required_single");
103 | });
104 |
--------------------------------------------------------------------------------
/tests/phantomjs.runner.js:
--------------------------------------------------------------------------------
1 | /*
2 | * QtWebKit-powered headless test runner using PhantomJS
3 | *
4 | * PhantomJS binaries: http://phantomjs.org/download.html
5 | * Requires PhantomJS 1.6+ (1.7+ recommended)
6 | *
7 | * Run with:
8 | * phantomjs runner.js [url-of-your-qunit-testsuite]
9 | *
10 | * e.g.
11 | * phantomjs runner.js http://localhost/qunit/test/index.html
12 | */
13 |
14 | /*jshint latedef:false */
15 | /*global phantom:false, require:false, console:false, window:false, QUnit:false */
16 |
17 | (function () {
18 | 'use strict';
19 |
20 | var args = require('system').args;
21 |
22 | // arg[0]: scriptName, args[1...]: arguments
23 | if (args.length !== 2) {
24 | console.error('Usage:\n phantomjs runner.js [url-of-your-qunit-testsuite]');
25 | phantom.exit(1);
26 | }
27 |
28 | var url = args[1],
29 | page = require('webpage').create();
30 |
31 | // Route `console.log()` calls from within the Page context to the main Phantom context (i.e. current `this`)
32 | page.onConsoleMessage = function (msg) {
33 | console.log(msg);
34 | };
35 |
36 | page.onInitialized = function () {
37 | page.evaluate(addLogging);
38 | };
39 |
40 | page.onCallback = function (message) {
41 | var result,
42 | failed;
43 |
44 | if (message) {
45 | if (message.name === 'QUnit.done') {
46 | result = message.data;
47 | failed = !result || result.failed;
48 |
49 | phantom.exit(failed ? 1 : 0);
50 | }
51 | }
52 | };
53 |
54 | page.open(url, function (status) {
55 | if (status !== 'success') {
56 | console.error('Unable to access network: ' + status);
57 | phantom.exit(1);
58 | } else {
59 | // Cannot do this verification with the 'DOMContentLoaded' handler because it
60 | // will be too late to attach it if a page does not have any script tags.
61 | var qunitMissing = page.evaluate(function () {
62 | return (typeof QUnit === 'undefined' || !QUnit);
63 | });
64 | if (qunitMissing) {
65 | console.error('The `QUnit` object is not present on this page.');
66 | phantom.exit(1);
67 | }
68 |
69 | // Do nothing... the callback mechanism will handle everything!
70 | }
71 | });
72 |
73 | function addLogging() {
74 | window.document.addEventListener('DOMContentLoaded', function () {
75 | var current_test_assertions = [];
76 |
77 | QUnit.log(function (details) {
78 | var response;
79 |
80 | // Ignore passing assertions
81 | if (details.result) {
82 | return;
83 | }
84 |
85 | response = details.message || '';
86 |
87 | if (typeof details.expected !== 'undefined') {
88 | if (response) {
89 | response += ', ';
90 | }
91 |
92 | response += 'expected: ' + details.expected + ', but was: ' + details.actual;
93 | if (details.source) {
94 | response += "\n" + details.source;
95 | }
96 | }
97 |
98 | current_test_assertions.push('Failed assertion: ' + response);
99 | });
100 |
101 | QUnit.testDone(function (result) {
102 | var i,
103 | len,
104 | name = result.module + ': ' + result.name;
105 |
106 | if (result.failed) {
107 | console.log('Test failed: ' + name);
108 |
109 | for (i = 0, len = current_test_assertions.length; i < len; i++) {
110 | console.log(' ' + current_test_assertions[i]);
111 | }
112 | }
113 |
114 | current_test_assertions.length = 0;
115 | });
116 |
117 | QUnit.done(function (result) {
118 | console.log('Took ' + result.runtime + 'ms to run ' + result.total + ' tests. ' + result.passed + ' passed, ' + result.failed + ' failed.');
119 |
120 | if (typeof window.callPhantom === 'function') {
121 | window.callPhantom({
122 | 'name': 'QUnit.done',
123 | 'data': result
124 | });
125 | }
126 | });
127 | }, false);
128 | }
129 | })();
--------------------------------------------------------------------------------
/kb/mappings.js:
--------------------------------------------------------------------------------
1 | sense.kb.addEndpointDescription('_mapping', {
2 | def_method: "GET",
3 | methods: ["GET", "PUT"],
4 | indices_mode: "multi",
5 | types_mode: "multi",
6 | data_autocomplete_rules: {
7 | "$TYPE$": {
8 | __template: {
9 | properties: {
10 | "FIELD": {}
11 | }
12 | },
13 | "_parent": {
14 | __template: {
15 | "type": ""
16 | },
17 | "type": "$TYPE$"
18 | },
19 | "index_analyzer": "standard",
20 | "search_analyzer": "standard",
21 | "analyzer": "standard",
22 | "dynamic_date_formats": ["yyyy-MM-dd"],
23 | "date_detection": { __one_of: [ true, false ]},
24 | "numeric_detection": { __one_of: [ true, false ]},
25 | "properties": {
26 | "*": {
27 | type: { __one_of: ["string", "float", "double", "byte", "short", "integer", "long", "date", "boolean",
28 | "binary", "object", "nested", "multi_field"]},
29 |
30 | // strings
31 | index_name: "",
32 | store: { __one_of: ["no", "yes"]},
33 | index: { __one_of: ["analyzed", "not_analyzed", "no"]},
34 | term_vector: { __one_of: ["no", "yes", "with_offsets", "with_positions", "with_positions_offsets"]},
35 | boost: 1.0,
36 | null_value: "",
37 | omit_norms: { __one_of: [ true, false]},
38 | index_options: { __one_of: [ "docs", "freqs", "positions"]},
39 | analyzer: "standard",
40 | index_analyzer: "standard",
41 | search_analyzer: "standard",
42 | include_in_all: { __one_of: [ false, true]},
43 | ignore_above: 10,
44 | position_offset_gap: 0,
45 |
46 | // numeric
47 | precision_step: 4,
48 | ignore_malformed: { __one_of: [ true, false]},
49 |
50 | // dates
51 | format: { __one_of: [ "basic_date", "basic_date_time", "basic_date_time_no_millis",
52 | "basic_ordinal_date", "basic_ordinal_date_time", "basic_ordinal_date_time_no_millis",
53 | "basic_time", "basic_time_no_millis", "basic_t_time", "basic_t_time_no_millis",
54 | "basic_week_date", "basic_week_date_time", "basic_week_date_time_no_millis",
55 | "date", "date_hour", "date_hour_minute", "date_hour_minute_second", "date_hour_minute_second_fraction",
56 | "date_hour_minute_second_millis", "date_optional_time", "date_time", "date_time_no_millis",
57 | "hour", "hour_minute", "hour_minute_second", "hour_minute_second_fraction", "hour_minute_second_millis",
58 | "ordinal_date", "ordinal_date_time", "ordinal_date_time_no_millis", "time", "time_no_millis",
59 | "t_time", "t_time_no_millis", "week_date", "week_date_time", "weekDateTimeNoMillis", "week_year",
60 | "weekyearWeek", "weekyearWeekDay", "year", "year_month", "year_month_day"]},
61 |
62 | fielddata: {
63 | filter: {
64 | regex: "",
65 | frequency: {
66 | min: 0.001,
67 | max: 0.1,
68 | min_segment_size: 500
69 | }
70 | }
71 | },
72 | postings_format: { __one_of: ["direct", "memory", "pulsing", "bloom_default", "bloom_pulsing", "default"]},
73 | similarity: { __one_of: [ "default", "BM25" ]},
74 |
75 | // objects
76 | properties: {
77 | __scope_link: "_mapping.$TYPE$.properties"
78 | },
79 |
80 | // multi_field
81 | path: { __one_of: [ "just_name", "full"]},
82 | fields: {
83 | "*": {
84 | __scope_link: "_mapping.$TYPE$.properties.$FIELD$"
85 | }
86 | }
87 | }
88 |
89 |
90 | }
91 | }
92 | }
93 | });
94 |
--------------------------------------------------------------------------------
/tests/src/curl_tests.js:
--------------------------------------------------------------------------------
1 | var global = window;
2 |
3 | module("CURL", {
4 | setup: function () {
5 | if (!global.sense)
6 | global.sense = {};
7 | var sense = global.sense;
8 | sense.tests = {};
9 | },
10 |
11 | teardown: function () {
12 | sense.tests = {};
13 | }
14 | });
15 |
16 | var notCURLS = [
17 | 'sldhfsljfhs',
18 | 's;kdjfsldkfj curl -XDELETE ""',
19 | '{ "hello": 1 }'
20 | ];
21 |
22 | var CURLS = [
23 | {
24 | "curl": "curl -XPUT 'http://localhost:9200/twitter/tweet/1' -d '{ \
25 | \"user\" : \"kimchy\", \
26 | \"post_date\" : \"2009-11-15T14:12:12\",\
27 | \"message\" : \"trying out Elastic Search\"\
28 | }'",
29 | "ret": {
30 | "server": "http://localhost:9200",
31 | "method": "PUT",
32 | "url": "/twitter/tweet/1",
33 | "data": "{ \
34 | \"user\" : \"kimchy\", \
35 | \"post_date\" : \"2009-11-15T14:12:12\",\
36 | \"message\" : \"trying out Elastic Search\"\
37 | }"
38 | }
39 | },
40 | {
41 | "curl": "curl -XGET \"localhost/twitter/tweet/1?version=2\" -d '{ \
42 | \"message\" : \"elasticsearch now has versioning support, double cool!\"\
43 | }'",
44 | "ret": {
45 | "server": "http://localhost",
46 | "method": "GET",
47 | "url": "/twitter/tweet/1?version=2",
48 | "data": "{ \
49 | \"message\" : \"elasticsearch now has versioning support, double cool!\"\
50 | }"
51 | }
52 | },
53 | {
54 | "curl": "curl -XPOST https://localhost/twitter/tweet/1?version=2 -d '{ \n\
55 | \"message\" : \"elasticsearch now has versioning support, double cool!\"\n\
56 | }'",
57 | "ret": {
58 | "server": "https://localhost",
59 | "method": "POST",
60 | "url": "/twitter/tweet/1?version=2",
61 | "data": "{ \n\
62 | \"message\" : \"elasticsearch now has versioning support, double cool!\"\n\
63 | }"
64 | }
65 | },
66 | {
67 | "curl": "curl -XPOST https://localhost/twitter",
68 | "ret": {
69 | "server": "https://localhost",
70 | "method": "POST",
71 | "url": "/twitter",
72 | "data": ""
73 | }
74 | },
75 | {
76 | "curl": "curl -X POST https://localhost/twitter/",
77 | "ret": {
78 | "server": "https://localhost",
79 | "method": "POST",
80 | "url": "/twitter/",
81 | "data": ""
82 | }
83 | },
84 | {
85 | "curl": "curl -s -XPOST localhost:9200/missing-test -d'\n\
86 | { \n\
87 | \"mappings\": {\n\
88 | }\n\
89 | }'",
90 | "ret": {
91 | "server": "http://localhost:9200",
92 | "method": "POST",
93 | "url": "/missing-test",
94 | "data": "{ \n\
95 | \"mappings\": {\n\
96 | }\n\
97 | }"
98 | }
99 | },
100 | {
101 | "curl": "curl 'localhost:9200/missing-test/doc/_search?pretty' -d'\n\
102 | {\n\
103 | \"query\": {\n\
104 | },\n\
105 | }'",
106 | "ret": {
107 | "server": "http://localhost:9200",
108 | "method": "",
109 | "url": "/missing-test/doc/_search?pretty",
110 | "data": "{\n\
111 | \"query\": {\n\
112 | },\n\
113 | }"
114 | }
115 | },
116 | {
117 | "curl": 'curl localhost:9200/ -d"\n\
118 | {\n\
119 | \\"query\\": {\n\
120 | },\n\
121 | }"',
122 | "ret": {
123 | "server": "http://localhost:9200",
124 | "method": "",
125 | "url": "/",
126 | "data": "{\n\
127 | \"query\": {\n\
128 | },\n\
129 | }"
130 | }
131 | }
132 | ];
133 |
134 |
135 | function compareCURL(result, expected) {
136 | deepEqual(result.server, expected.server);
137 | deepEqual(result.method, expected.method);
138 | deepEqual(result.url, expected.url);
139 | deepEqual(result.data, expected.data);
140 | }
141 |
142 | for (var i = 0; i < notCURLS.length; i++)
143 |
144 | test("cURL Detection - broken strings " + i, function (c) {
145 | return function () {
146 | ok(!global.sense.curl.detectCURL(notCURLS[c]), "marked as curl while it wasn't:" + notCURLS[c]);
147 | }
148 | }(i)
149 | );
150 |
151 | for (var i = 0; i < CURLS.length; i++)
152 |
153 |
154 | test("cURL Detection - correct strings " + i, function (c) {
155 | return function () {
156 | ok(global.sense.curl.detectCURL(CURLS[c].curl), "marked as not curl while it was:" + CURLS[c].curl);
157 | var r = global.sense.curl.parseCURL(CURLS[c].curl);
158 | compareCURL(r, CURLS[c].ret);
159 | }
160 | }(i)
161 | );
162 |
163 |
--------------------------------------------------------------------------------
/src/kb.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | var global = window;
4 | var GLOBAL_AUTOCOMPLETE_RULES = {}, ES_SCHEME_BY_ENDPOINT = {};
5 |
6 | function escapeRegex(text) {
7 | return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
8 | }
9 |
10 | function addGlobalAutocompleteRules(parentNode, rules) {
11 | GLOBAL_AUTOCOMPLETE_RULES[parentNode] = rules;
12 | }
13 |
14 | function getGlobalAutocompleteRules() {
15 | return GLOBAL_AUTOCOMPLETE_RULES;
16 | }
17 |
18 |
19 | function addEndpointDescription(endpoint, description) {
20 | if (!description.endpoint_autocomplete)
21 | description.endpoint_autocomplete = [endpoint];
22 |
23 | if (!description.match) {
24 | var l = $.map(description.endpoint_autocomplete, escapeRegex);
25 | description.match = "(?:" + l.join(")|(?:") + ")";
26 | }
27 |
28 | if (typeof description.match == "string") description.match = new RegExp(description.match);
29 |
30 | var copiedDescription = {};
31 | $.extend(copiedDescription, description);
32 | copiedDescription._id = endpoint;
33 |
34 | ES_SCHEME_BY_ENDPOINT[endpoint] = copiedDescription;
35 | }
36 |
37 | function getEndpointDescriptionByEndpoint(endpoint) {
38 | return ES_SCHEME_BY_ENDPOINT[endpoint];
39 | }
40 |
41 | function getEndpointsForIndicesTypesAndId(indices, types, id) {
42 | var ret = [];
43 | var index_mode = "none";
44 | if (indices && indices.length > 0) {
45 | indices = sense.mappings.expandAliases(indices);
46 | index_mode = typeof indices == "string" ? "single" : "multi";
47 | }
48 |
49 | var type_mode = "none";
50 | if (types && types.length > 0) type_mode = types.length > 1 ? "multi" : "single";
51 | var id_mode = "none";
52 | if (id && id.length > 0) id_mode = "single";
53 |
54 | for (var endpoint in ES_SCHEME_BY_ENDPOINT) {
55 | var scheme = ES_SCHEME_BY_ENDPOINT[endpoint];
56 | switch (scheme.indices_mode) {
57 | case "none":
58 | if (index_mode !== "none") continue;
59 | break;
60 | case "single":
61 | if (index_mode !== "single") continue;
62 | break;
63 | case "required_multi":
64 | if (index_mode === "none") continue;
65 | break;
66 | case "multi": // always good
67 | break;
68 | }
69 | switch (scheme.types_mode) {
70 | case "none":
71 | if (type_mode !== "none") continue;
72 | break;
73 | case "single":
74 | if (type_mode !== "single") continue;
75 | break;
76 | case "multi": // always good
77 | break;
78 | }
79 |
80 | switch (scheme.doc_id_mode) {
81 | case "none":
82 | if (id_mode !== "none") continue;
83 | break;
84 | case "required_single":
85 | if (id_mode === "none") continue;
86 | break;
87 | }
88 |
89 | ret.push(endpoint);
90 | }
91 | return ret;
92 | }
93 |
94 | function getEndpointDescriptionByPath(path, indices, types, id) {
95 | var endpoints = getEndpointsForIndicesTypesAndId(indices, types, id);
96 | for (var i = 0; i < endpoints.length; i++) {
97 | var scheme = ES_SCHEME_BY_ENDPOINT[endpoints[i]];
98 | if (scheme.match.test(path || "")) return scheme;
99 | }
100 | return null;
101 | }
102 |
103 | function getEndpointAutocomplete(indices, types, id) {
104 | var ret = [];
105 | var endpoints = getEndpointsForIndicesTypesAndId(indices, types, id);
106 | for (var i = 0; i < endpoints.length; i++) {
107 | var scheme = ES_SCHEME_BY_ENDPOINT[endpoints[i]];
108 | ret.push.apply(ret, scheme.endpoint_autocomplete);
109 | }
110 | return ret;
111 | }
112 |
113 | function clear() {
114 | ES_SCHEME_BY_ENDPOINT = {};
115 | GLOBAL_AUTOCOMPLETE_RULES = {};
116 | }
117 |
118 | if (!global.sense) global.sense = {};
119 | global.sense.kb = {};
120 | global.sense.kb.addGlobalAutocompleteRules = addGlobalAutocompleteRules;
121 | global.sense.kb.getGlobalAutocompleteRules = getGlobalAutocompleteRules;
122 | global.sense.kb.addEndpointDescription = addEndpointDescription;
123 | global.sense.kb.getEndpointAutocomplete = getEndpointAutocomplete;
124 | global.sense.kb.getEndpointDescriptionByPath = getEndpointDescriptionByPath;
125 | global.sense.kb.getEndpointDescriptionByEndpoint = getEndpointDescriptionByEndpoint;
126 | global.sense.kb.clear = clear;
127 |
128 |
129 | })();
--------------------------------------------------------------------------------
/lib/src-noconflict/theme-monokai.js:
--------------------------------------------------------------------------------
1 | /* ***** BEGIN LICENSE BLOCK *****
2 | * Distributed under the BSD license:
3 | *
4 | * Copyright (c) 2010, Ajax.org B.V.
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without
8 | * modification, are permitted provided that the following conditions are met:
9 | * * Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * * Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * * Neither the name of Ajax.org B.V. nor the
15 | * names of its contributors may be used to endorse or promote products
16 | * derived from this software without specific prior written permission.
17 | *
18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
22 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 | *
29 | * ***** END LICENSE BLOCK ***** */
30 |
31 | ace.define('ace/theme/monokai', ['require', 'exports', 'module' , 'ace/lib/dom'], function(require, exports, module) {
32 |
33 | exports.isDark = true;
34 | exports.cssClass = "ace-monokai";
35 | exports.cssText = ".ace-monokai .ace_gutter {\
36 | background: #2f3129;\
37 | color: #f1f1f1\
38 | }\
39 | .ace-monokai .ace_print-margin {\
40 | width: 1px;\
41 | background: #555651\
42 | }\
43 | .ace-monokai .ace_scroller {\
44 | background-color: #272822\
45 | }\
46 | .ace-monokai .ace_text-layer {\
47 | color: #F8F8F2\
48 | }\
49 | .ace-monokai .ace_cursor {\
50 | border-left: 2px solid #F8F8F0\
51 | }\
52 | .ace-monokai .ace_overwrite-cursors .ace_cursor {\
53 | border-left: 0px;\
54 | border-bottom: 1px solid #F8F8F0\
55 | }\
56 | .ace-monokai .ace_marker-layer .ace_selection {\
57 | background: #49483E\
58 | }\
59 | .ace-monokai.ace_multiselect .ace_selection.ace_start {\
60 | box-shadow: 0 0 3px 0px #272822;\
61 | border-radius: 2px\
62 | }\
63 | .ace-monokai .ace_marker-layer .ace_step {\
64 | background: rgb(102, 82, 0)\
65 | }\
66 | .ace-monokai .ace_marker-layer .ace_bracket {\
67 | margin: -1px 0 0 -1px;\
68 | border: 1px solid #49483E\
69 | }\
70 | .ace-monokai .ace_marker-layer .ace_active-line {\
71 | background: #202020\
72 | }\
73 | .ace-monokai .ace_gutter-active-line {\
74 | background-color: #272727\
75 | }\
76 | .ace-monokai .ace_marker-layer .ace_selected-word {\
77 | border: 1px solid #49483E\
78 | }\
79 | .ace-monokai .ace_invisible {\
80 | color: #49483E\
81 | }\
82 | .ace-monokai .ace_entity.ace_name.ace_tag,\
83 | .ace-monokai .ace_keyword,\
84 | .ace-monokai .ace_meta,\
85 | .ace-monokai .ace_storage {\
86 | color: #F92672\
87 | }\
88 | .ace-monokai .ace_constant.ace_character,\
89 | .ace-monokai .ace_constant.ace_language,\
90 | .ace-monokai .ace_constant.ace_numeric,\
91 | .ace-monokai .ace_constant.ace_other {\
92 | color: #AE81FF\
93 | }\
94 | .ace-monokai .ace_invalid {\
95 | color: #F8F8F0;\
96 | background-color: #F92672\
97 | }\
98 | .ace-monokai .ace_invalid.ace_deprecated {\
99 | color: #F8F8F0;\
100 | background-color: #AE81FF\
101 | }\
102 | .ace-monokai .ace_support.ace_constant,\
103 | .ace-monokai .ace_support.ace_function {\
104 | color: #66D9EF\
105 | }\
106 | .ace-monokai .ace_fold {\
107 | background-color: #A6E22E;\
108 | border-color: #F8F8F2\
109 | }\
110 | .ace-monokai .ace_storage.ace_type,\
111 | .ace-monokai .ace_support.ace_class,\
112 | .ace-monokai .ace_support.ace_type {\
113 | font-style: italic;\
114 | color: #66D9EF\
115 | }\
116 | .ace-monokai .ace_entity.ace_name.ace_function,\
117 | .ace-monokai .ace_entity.ace_other.ace_attribute-name,\
118 | .ace-monokai .ace_variable {\
119 | color: #A6E22E\
120 | }\
121 | .ace-monokai .ace_variable.ace_parameter {\
122 | font-style: italic;\
123 | color: #FD971F\
124 | }\
125 | .ace-monokai .ace_string {\
126 | color: #E6DB74\
127 | }\
128 | .ace-monokai .ace_comment {\
129 | color: #75715E\
130 | }\
131 | .ace-monokai .ace_markup.ace_underline {\
132 | text-decoration: underline\
133 | }\
134 | .ace-monokai .ace_indent-guide {\
135 | background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNQ11D6z7Bq1ar/ABCKBG6g04U2AAAAAElFTkSuQmCC) right repeat-y\
136 | }";
137 |
138 | var dom = require("../lib/dom");
139 | dom.importCssString(exports.cssText, exports.cssClass);
140 | });
141 |
--------------------------------------------------------------------------------
/sense.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | overflow: hidden;
4 | }
5 |
6 | .pull-right-btn {
7 | float: right;
8 | margin-right: 5px;
9 | }
10 |
11 | .pull-right-btn:first-of-type {
12 | margin-right: 0;
13 | }
14 |
15 | #es_method {
16 | width: 100px;
17 | }
18 |
19 | #editor_actions {
20 | position: absolute;
21 | top: 47px;
22 | right: 100%;
23 | margin-right: -481px;
24 | z-index: 100;
25 | }
26 |
27 | #editor_actions > .btn-group > a {
28 | padding: 2px 4px;
29 | }
30 |
31 | #editor_actions > .btn-group > a:hover {
32 | padding: 2px 4px;
33 | text-decoration: none;
34 | }
35 |
36 | #request_wrench {
37 | color: rgb(51, 51, 51);
38 | }
39 |
40 | #send {
41 | color: rgb(112, 186, 86);
42 | }
43 |
44 | .editor_position {
45 | position: absolute;
46 | top: 50px;
47 | bottom: 0;
48 | left: 0;
49 | width: 484px;
50 | }
51 |
52 | .overlay {
53 | background-color: #000;
54 | opacity: 0.5;
55 | z-index: 100;
56 | }
57 |
58 | #output {
59 | position: absolute;
60 | top: 50px;
61 | bottom: 0;
62 | left: 484px;
63 | right: 0;
64 | min-width: 700px;
65 | }
66 |
67 | #autocomplete {
68 | visibility: hidden;
69 | position: absolute;
70 | z-index: 1000;
71 | margin-top: 22px;
72 | /*font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;*/
73 | /*font-size: 12px;*/
74 | /*max-height: 100px;*/
75 | /*overflow-y: auto;*/
76 | /* prevent horizontal scrollbar */
77 | /*overflow-x: hidden;*/
78 | }
79 |
80 | .ui-menu {
81 | background-color: white;
82 | border: 1px solid #CCC
83 | }
84 |
85 | .ui-state-focus {
86 | color: white;
87 | background-color: #08C;
88 | margin: auto !important;
89 | }
90 |
91 | #history_popup {
92 | width: 90%;
93 | margin-left: -45%;
94 | height: 90%;
95 | top: 5%;
96 | margin-top: 0;
97 | }
98 |
99 | #history_popup .modal-body {
100 | }
101 |
102 | #history_popup .modal-header {
103 | position: absolute;
104 | top: 0;
105 | left: 0;
106 | right: 0;
107 | }
108 |
109 | #history_popup .modal-footer {
110 | position: absolute;
111 | bottom: 0;
112 | left: 0;
113 | right: 0;
114 | }
115 |
116 | #history_popup .nav {
117 | position: absolute;
118 | width: 400px;
119 | left: 0;
120 | top: 60px;
121 | bottom: 70px;
122 | overflow-y: auto;
123 | }
124 |
125 | #example_editor_container {
126 | width: 100%;
127 | height: 10em;
128 | margin: 10px 0;
129 | position: relative;
130 | }
131 |
132 | #example_editor_container #example_editor {
133 | top: 0;
134 | bottom: 0;
135 | right: 0;
136 | left: 0;
137 | }
138 |
139 | .icon-chevron-right {
140 | position: absolute;
141 | right: 10px;
142 | margin-top: 2px;
143 | margin-right: -6px;
144 | opacity: .25;
145 | }
146 |
147 | #history_popup .nav a {
148 | display: block;
149 | margin: 0 0 -1px;
150 | padding: 8px 14px;
151 | border: 1px solid #e5e5e5;
152 | white-space: nowrap;
153 | position: relative;
154 | overflow: hidden;
155 | }
156 |
157 | #history_popup .nav li:first-child > a {
158 | -webkit-border-radius: 6px 6px 0 0;
159 | -moz-border-radius: 6px 6px 0 0;
160 | border-radius: 6px 6px 0 0;
161 | }
162 |
163 | #history_popup .nav li:last-child > a {
164 | -webkit-border-radius: 0 0 6px 6px;
165 | -moz-border-radius: 0 0 6px 6px;
166 | border-radius: 0 0 6px 6px;
167 | }
168 |
169 | #history_viewer {
170 | position: absolute;
171 | left: 430px;
172 | right: 0;
173 | margin-right: 9px;
174 | top: 60px;
175 | bottom: 70px;
176 | }
177 |
178 | #welcome_popup {
179 | top: 40%;
180 | }
181 |
182 | #welcome_popup .modal-body {
183 | max-height: 600px;
184 | }
185 |
186 | .ui-autocomplete {
187 | z-index: 400 !important;
188 | }
189 |
190 | .out_of_screen {
191 | width: 1px;
192 | height: 1px;
193 | overflow: hidden;
194 | margin-left: -1000px;
195 | }
196 |
197 | .ace_url {
198 | color: #0088cc;
199 | }
200 |
201 | .ace_url.ace_param {
202 | color: rgb(49, 132, 149);
203 | }
204 |
205 | .ace_url.ace_value {
206 | color: rgb(3, 106, 7);
207 | }
208 |
209 | .ace_method {
210 | color: rgb(197, 6, 11);
211 | }
212 |
213 | .ace_snippet-marker {
214 | box-sizing: border-box;
215 | background: rgba(194, 193, 208, 0.20);
216 | /*border: 1px dotted rgba(211, 208, 235, 0.62); */
217 | position: absolute;
218 | width: 100% !important;
219 | }
220 |
221 | .ace_snippet-marker.ace_start {
222 | border-top: dotted 1px rgba(194, 193, 208, 0.80);
223 | }
224 |
225 | .ace_snippet-marker.ace_start + .ace_snippet-marker {
226 | border-bottom: dotted 1px rgba(194, 193, 208, 0.80);
227 | }
228 |
229 | .ui-resizable-e {
230 | cursor: ew-resize;
231 | width: 10px;
232 | right: -5px;
233 | top: 0;
234 | bottom: 0;
235 | background-color: transparent;
236 | position: absolute;
237 | z-index: 50 !important;
238 | }
239 |
240 | .ui-resizable-e:hover {
241 | background-color: rgba(194, 193, 208, 0.80);
242 | }
243 |
244 | .ui-resizable-e.active {
245 | background-color: rgba(194, 193, 208, 100);
246 | }
--------------------------------------------------------------------------------
/tests/src/utils_tests.js:
--------------------------------------------------------------------------------
1 | var sense = window.sense;
2 | var utils = sense.utils;
3 |
4 | module("Utils", {
5 | setup: function () {
6 | sense.tests = {};
7 | sense.tests.editor_div = $('
').appendTo($('body'));
8 | sense.tests.editor = ace.edit("editor");
9 | ace.require("ace/mode/sense");
10 | sense.tests.editor.getSession().setMode("ace/mode/sense");
11 | sense.tests.editor.getSession().setValue("hello");
12 |
13 | },
14 |
15 | teardown: function () {
16 | sense.tests.editor_div.remove();
17 | sense.tests = {};
18 | }
19 | });
20 |
21 | var testCount = 0;
22 |
23 | function utils_test(name, prefix, data, test) {
24 | if (data && typeof data != "string") data = JSON.stringify(data, null, 3);
25 | if (data) {
26 | if (prefix) data = prefix + "\n" + data;
27 | } else {
28 | data = prefix;
29 | }
30 |
31 | QUnit.asyncTest("Utils test " + testCount++ + ":" + name,
32 | function () {
33 | var editor = sense.tests.editor;
34 | utils.updateEditorAndCallWhenUpdated(data, editor, function () {
35 | test(editor);
36 | start();
37 | });
38 |
39 | });
40 | }
41 |
42 | var simple_request =
43 | { prefix: 'POST _search',
44 | data: '{\n' +
45 | ' "query": { "match_all": {} }\n' +
46 | '}'
47 | };
48 |
49 | var single_line_request =
50 | { prefix: 'POST _search',
51 | data: '{ "query": { "match_all": {} } }'
52 | };
53 |
54 |
55 | utils_test("simple request range", simple_request.prefix, simple_request.data,
56 | function (editor) {
57 | var range = utils.getCurrentRequestRange(editor);
58 | var expected = new (ace.require("ace/range").Range)(
59 | 0, 0,
60 | 3, 1
61 | );
62 | deepEqual(range, expected);
63 | }
64 | );
65 |
66 | utils_test("single line request range", single_line_request.prefix, single_line_request.data,
67 | function (editor) {
68 | var range = utils.getCurrentRequestRange(editor);
69 | var expected = new (ace.require("ace/range").Range)(
70 | 0, 0,
71 | 1, 32
72 | );
73 | deepEqual(range, expected);
74 | }
75 | );
76 |
77 | utils_test("simple request data", simple_request.prefix, simple_request.data,
78 | function (editor) {
79 | var request = utils.getCurrentRequest(editor);
80 | var expected = {
81 | method: "POST",
82 | url: "_search",
83 | data: [simple_request.data]
84 | };
85 |
86 | deepEqual(request, expected);
87 | }
88 | );
89 |
90 | utils_test("single line request data", single_line_request.prefix, single_line_request.data,
91 | function (editor) {
92 | var request = utils.getCurrentRequest(editor);
93 | var expected = {
94 | method: "POST",
95 | url: "_search",
96 | data: [single_line_request.data]
97 | };
98 |
99 | deepEqual(request, expected);
100 | }
101 | );
102 |
103 |
104 | var get_request_no_data =
105 | { prefix: 'GET _stats'
106 | };
107 |
108 | utils_test("request with no data followed by a new line", get_request_no_data.prefix, "\n",
109 | function (editor) {
110 | var range = utils.getCurrentRequestRange(editor);
111 | var expected = new (ace.require("ace/range").Range)(
112 | 0, 0,
113 | 0, 10
114 | );
115 | deepEqual(range, expected);
116 | }
117 | );
118 |
119 | utils_test("request with no data followed by a new line (data)", get_request_no_data.prefix, "\n",
120 | function (editor) {
121 | var range = utils.getCurrentRequest(editor);
122 | var expected = {
123 | method: "GET",
124 | url: "_stats",
125 | data: []
126 | };
127 |
128 | deepEqual(range, expected);
129 | }
130 | );
131 |
132 |
133 | utils_test("request with no data", get_request_no_data.prefix, get_request_no_data.data,
134 | function (editor) {
135 | var range = utils.getCurrentRequestRange(editor);
136 | var expected = new (ace.require("ace/range").Range)(
137 | 0, 0,
138 | 0, 10
139 | );
140 | deepEqual(range, expected);
141 | }
142 | );
143 |
144 | utils_test("request with no data (data)", get_request_no_data.prefix, get_request_no_data.data,
145 | function (editor) {
146 | var range = utils.getCurrentRequest(editor);
147 | var expected = {
148 | method: "GET",
149 | url: "_stats",
150 | data: []
151 | };
152 |
153 | deepEqual(range, expected);
154 | }
155 | );
156 |
157 |
158 | var multi_doc_request =
159 | { prefix: 'POST _bulk',
160 | data_as_array: ['{ "index": { "_index": "index", "_type":"type" } }',
161 | '{ "field": 1 }'
162 | ]
163 | };
164 | multi_doc_request.data = multi_doc_request.data_as_array.join("\n");
165 |
166 | utils_test("multi doc request range", multi_doc_request.prefix, multi_doc_request.data,
167 | function (editor) {
168 | var range = utils.getCurrentRequestRange(editor);
169 | var expected = new (ace.require("ace/range").Range)(
170 | 0, 0,
171 | 2, 14
172 | );
173 | deepEqual(range, expected);
174 | }
175 | );
176 |
177 | utils_test("multi doc request data", multi_doc_request.prefix, multi_doc_request.data,
178 | function (editor) {
179 | var request = utils.getCurrentRequest(editor);
180 | var expected = {
181 | method: "POST",
182 | url: "_bulk",
183 | data: multi_doc_request.data_as_array
184 | };
185 |
186 | deepEqual(request, expected);
187 | }
188 | );
189 |
--------------------------------------------------------------------------------
/tests/src/mapping_tests.js:
--------------------------------------------------------------------------------
1 | var global = window;
2 |
3 | module("Mappings", {
4 | setup: function () {
5 | if (!global.sense)
6 | global.sense = {};
7 | var sense = global.sense;
8 | sense.tests = {};
9 | },
10 |
11 | teardown: function () {
12 | sense.tests = {};
13 | }
14 | });
15 |
16 |
17 | test("Multi fields", function () {
18 | global.sense.mappings.loadMappings({
19 | "index": {
20 | "tweet": {
21 | "properties": {
22 | "first_name": {
23 | "type": "multi_field",
24 | "path": "just_name",
25 | "fields": {
26 | "first_name": {"type": "string", "index": "analyzed"},
27 | "any_name": {"type": "string", "index": "analyzed"}
28 | }
29 | },
30 | "last_name": {
31 | "type": "multi_field",
32 | "path": "just_name",
33 | "fields": {
34 | "last_name": {"type": "string", "index": "analyzed"},
35 | "any_name": {"type": "string", "index": "analyzed"}
36 | }
37 | }
38 | }
39 | }}
40 | });
41 |
42 | deepEqual(global.sense.mappings.getFields("index").sort(), ["any_name", "first_name", "last_name" ]);
43 | });
44 |
45 | test("Simple fields", function () {
46 | global.sense.mappings.loadMappings({
47 | "index": {
48 | "tweet": {
49 | "properties": {
50 | "str": {
51 | "type": "string"
52 | },
53 | "number": {
54 | "type": "int"
55 | }
56 | }
57 | }}
58 | });
59 |
60 | deepEqual(global.sense.mappings.getFields("index").sort(), ["number", "str" ]);
61 | });
62 |
63 |
64 | test("Nested fields", function () {
65 | global.sense.mappings.loadMappings({
66 | "index": {
67 | "tweet": {
68 | "properties": {
69 | "person": {
70 | "type": "object",
71 | "properties": {
72 | "name": {
73 | "properties": {
74 | "first_name": {"type": "string"},
75 | "last_name": {"type": "string"}
76 | }
77 | },
78 | "sid": {"type": "string", "index": "not_analyzed"}
79 | }
80 | },
81 | "message": {"type": "string"}
82 | }
83 | }
84 | }});
85 |
86 | deepEqual(global.sense.mappings.getFields("index", ["tweet"]).sort(),
87 | ["message", "person.name.first_name", "person.name.last_name", "person.sid" ]);
88 | });
89 |
90 | test("Enabled fields", function () {
91 | global.sense.mappings.loadMappings({
92 | "index": {
93 | "tweet": {
94 | "properties": {
95 | "person": {
96 | "type": "object",
97 | "properties": {
98 | "name": {
99 | "type": "object",
100 | "enabled": false
101 | },
102 | "sid": {"type": "string", "index": "not_analyzed"}
103 | }
104 | },
105 | "message": {"type": "string"}
106 | }
107 | }
108 | }
109 | });
110 |
111 | deepEqual(global.sense.mappings.getFields("index", ["tweet"]).sort(),
112 | ["message", "person.sid" ]);
113 | });
114 |
115 |
116 | test("Path tests", function () {
117 | global.sense.mappings.loadMappings({
118 | "index": {
119 | "person": {
120 | "properties": {
121 | "name1": {
122 | "type": "object",
123 | "path": "just_name",
124 | "properties": {
125 | "first1": {"type": "string"},
126 | "last1": {"type": "string", "index_name": "i_last_1"}
127 | }
128 | },
129 | "name2": {
130 | "type": "object",
131 | "path": "full",
132 | "properties": {
133 | "first2": {"type": "string"},
134 | "last2": {"type": "string", "index_name": "i_last_2"}
135 | }
136 | }
137 | }
138 | }
139 | }
140 | });
141 |
142 | deepEqual(global.sense.mappings.getFields().sort(),
143 | ["first1", "i_last_1", "name2.first2", "name2.i_last_2" ]);
144 | });
145 |
146 | test("Use index_name tests", function () {
147 | global.sense.mappings.loadMappings({
148 | "index": {
149 | "person": {
150 | "properties": {
151 | "last1": {"type": "string", "index_name": "i_last_1"}
152 | }
153 | }
154 | }
155 | });
156 |
157 | deepEqual(global.sense.mappings.getFields().sort(),
158 | [ "i_last_1" ]);
159 | });
160 |
161 | test("Aliases", function () {
162 | global.sense.mappings.loadAliases({
163 | "test_index1": {
164 | "aliases": {
165 | "alias1": {}
166 | }
167 | },
168 | "test_index2": {
169 | "aliases": {
170 | "alias2": {
171 | "filter": {
172 | "term": {
173 | "FIELD": "VALUE"
174 | }
175 | }
176 | },
177 | "alias1": {}
178 | }
179 | }
180 | });
181 | global.sense.mappings.loadMappings({
182 | "test_index1": {
183 | "type1": {
184 | "properties": {
185 | "last1": {"type": "string", "index_name": "i_last_1"}
186 | }
187 | }
188 | },
189 | "test_index2": {
190 | "type2": {
191 | "properties": {
192 | "last1": {"type": "string", "index_name": "i_last_1"}
193 | }
194 | }
195 | }
196 | });
197 |
198 | deepEqual(global.sense.mappings.getIndices().sort(),
199 | [ "_all", "alias1", "alias2", "test_index1", "test_index2" ]
200 | );
201 | deepEqual(global.sense.mappings.getIndices(false).sort(),
202 | ["test_index1", "test_index2" ]
203 | );
204 | deepEqual(global.sense.mappings.expandAliases(["alias1", "test_index2"]).sort(),
205 | ["test_index1", "test_index2" ]
206 | );
207 | deepEqual(global.sense.mappings.expandAliases("alias2"), "test_index2");
208 | });
209 |
210 |
--------------------------------------------------------------------------------
/tests/lib/qunit-1.10.0.css:
--------------------------------------------------------------------------------
1 | /**
2 | * QUnit v1.10.0 - A JavaScript Unit Testing Framework
3 | *
4 | * http://qunitjs.com
5 | *
6 | * Copyright 2012 jQuery Foundation and other contributors
7 | * Released under the MIT license.
8 | * http://jquery.org/license
9 | */
10 |
11 | /** Font Family and Sizes */
12 |
13 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
14 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
15 | }
16 |
17 | #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li {
18 | font-size: small;
19 | }
20 |
21 | #qunit-tests {
22 | font-size: smaller;
23 | }
24 |
25 | /** Resets */
26 |
27 | #qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
28 | margin: 0;
29 | padding: 0;
30 | }
31 |
32 | /** Header */
33 |
34 | #qunit-header {
35 | padding: 0.5em 0 0.5em 1em;
36 |
37 | color: #8699a4;
38 | background-color: #0d3349;
39 |
40 | font-size: 1.5em;
41 | line-height: 1em;
42 | font-weight: normal;
43 |
44 | border-radius: 5px 5px 0 0;
45 | -moz-border-radius: 5px 5px 0 0;
46 | -webkit-border-top-right-radius: 5px;
47 | -webkit-border-top-left-radius: 5px;
48 | }
49 |
50 | #qunit-header a {
51 | text-decoration: none;
52 | color: #c2ccd1;
53 | }
54 |
55 | #qunit-header a:hover,
56 | #qunit-header a:focus {
57 | color: #fff;
58 | }
59 |
60 | #qunit-testrunner-toolbar label {
61 | display: inline-block;
62 | padding: 0 .5em 0 .1em;
63 | }
64 |
65 | #qunit-banner {
66 | height: 5px;
67 | }
68 |
69 | #qunit-testrunner-toolbar {
70 | padding: 0.5em 0 0.5em 2em;
71 | color: #5E740B;
72 | background-color: #eee;
73 | overflow: hidden;
74 | }
75 |
76 | #qunit-userAgent {
77 | padding: 0.5em 0 0.5em 2.5em;
78 | background-color: #2b81af;
79 | color: #fff;
80 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
81 | }
82 |
83 | #qunit-modulefilter-container {
84 | float: right;
85 | }
86 |
87 | /** Tests: Pass/Fail */
88 |
89 | #qunit-tests {
90 | list-style-position: inside;
91 | }
92 |
93 | #qunit-tests li {
94 | padding: 0.4em 0.5em 0.4em 2.5em;
95 | border-bottom: 1px solid #fff;
96 | list-style-position: inside;
97 | }
98 |
99 | #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
100 | display: none;
101 | }
102 |
103 | #qunit-tests li strong {
104 | cursor: pointer;
105 | }
106 |
107 | #qunit-tests li a {
108 | padding: 0.5em;
109 | color: #c2ccd1;
110 | text-decoration: none;
111 | }
112 |
113 | #qunit-tests li a:hover,
114 | #qunit-tests li a:focus {
115 | color: #000;
116 | }
117 |
118 | #qunit-tests ol {
119 | margin-top: 0.5em;
120 | padding: 0.5em;
121 |
122 | background-color: #fff;
123 |
124 | border-radius: 5px;
125 | -moz-border-radius: 5px;
126 | -webkit-border-radius: 5px;
127 | }
128 |
129 | #qunit-tests table {
130 | border-collapse: collapse;
131 | margin-top: .2em;
132 | }
133 |
134 | #qunit-tests th {
135 | text-align: right;
136 | vertical-align: top;
137 | padding: 0 .5em 0 0;
138 | }
139 |
140 | #qunit-tests td {
141 | vertical-align: top;
142 | }
143 |
144 | #qunit-tests pre {
145 | margin: 0;
146 | white-space: pre-wrap;
147 | word-wrap: break-word;
148 | }
149 |
150 | #qunit-tests del {
151 | background-color: #e0f2be;
152 | color: #374e0c;
153 | text-decoration: none;
154 | }
155 |
156 | #qunit-tests ins {
157 | background-color: #ffcaca;
158 | color: #500;
159 | text-decoration: none;
160 | }
161 |
162 | /*** Test Counts */
163 |
164 | #qunit-tests b.counts {
165 | color: black;
166 | }
167 |
168 | #qunit-tests b.passed {
169 | color: #5E740B;
170 | }
171 |
172 | #qunit-tests b.failed {
173 | color: #710909;
174 | }
175 |
176 | #qunit-tests li li {
177 | padding: 5px;
178 | background-color: #fff;
179 | border-bottom: none;
180 | list-style-position: inside;
181 | }
182 |
183 | /*** Passing Styles */
184 |
185 | #qunit-tests li li.pass {
186 | color: #3c510c;
187 | background-color: #fff;
188 | border-left: 10px solid #C6E746;
189 | }
190 |
191 | #qunit-tests .pass {
192 | color: #528CE0;
193 | background-color: #D2E0E6;
194 | }
195 |
196 | #qunit-tests .pass .test-name {
197 | color: #366097;
198 | }
199 |
200 | #qunit-tests .pass .test-actual,
201 | #qunit-tests .pass .test-expected {
202 | color: #999999;
203 | }
204 |
205 | #qunit-banner.qunit-pass {
206 | background-color: #C6E746;
207 | }
208 |
209 | /*** Failing Styles */
210 |
211 | #qunit-tests li li.fail {
212 | color: #710909;
213 | background-color: #fff;
214 | border-left: 10px solid #EE5757;
215 | white-space: pre;
216 | }
217 |
218 | #qunit-tests > li:last-child {
219 | border-radius: 0 0 5px 5px;
220 | -moz-border-radius: 0 0 5px 5px;
221 | -webkit-border-bottom-right-radius: 5px;
222 | -webkit-border-bottom-left-radius: 5px;
223 | }
224 |
225 | #qunit-tests .fail {
226 | color: #000000;
227 | background-color: #EE5757;
228 | }
229 |
230 | #qunit-tests .fail .test-name,
231 | #qunit-tests .fail .module-name {
232 | color: #000000;
233 | }
234 |
235 | #qunit-tests .fail .test-actual {
236 | color: #EE5757;
237 | }
238 |
239 | #qunit-tests .fail .test-expected {
240 | color: green;
241 | }
242 |
243 | #qunit-banner.qunit-fail {
244 | background-color: #EE5757;
245 | }
246 |
247 | /** Result */
248 |
249 | #qunit-testresult {
250 | padding: 0.5em 0.5em 0.5em 2.5em;
251 |
252 | color: #2b81af;
253 | background-color: #D2E0E6;
254 |
255 | border-bottom: 1px solid white;
256 | }
257 |
258 | #qunit-testresult .module-name {
259 | font-weight: bold;
260 | }
261 |
262 | /** Fixture */
263 |
264 | #qunit-fixture {
265 | position: absolute;
266 | top: -10000px;
267 | left: -10000px;
268 | width: 1000px;
269 | height: 1000px;
270 | }
271 |
--------------------------------------------------------------------------------
/kb/filter.js:
--------------------------------------------------------------------------------
1 | sense.kb.addGlobalAutocompleteRules("filter", {
2 | and: {
3 | __template: {
4 | filters: [
5 | {}
6 | ]
7 | },
8 | filters: [
9 | { __scope_link: ".filter" }
10 | ],
11 | _cache: {__one_of: [ false, true ]}
12 | },
13 | bool: {
14 | must: [
15 | { __scope_link: ".filter"}
16 | ],
17 | must_not: [
18 | { __scope_link: ".filter"}
19 | ],
20 | should: [
21 | { __scope_link: ".filter"}
22 | ],
23 | _cache: {__one_of: [ false, true ]}
24 | },
25 | exists: {
26 | __template: { "FIELD": "VALUE"},
27 | "$FIELD$": ""
28 | },
29 | ids: {
30 | __template: { "values": ["ID"] },
31 | "type": "$TYPE$",
32 | "values": [""]
33 | },
34 | limit: {
35 | __template: { value: 100},
36 | value: 100
37 | },
38 | type: {
39 | __template: { value: "TYPE"},
40 | value: "$TYPE$"
41 | },
42 | geo_bounding_box: {
43 | __template: {
44 | "FIELD": {
45 | "top_left": {
46 | "lat": 40.73,
47 | "lon": -74.1
48 | },
49 | "bottom_right": {
50 | "lat": 40.717,
51 | "lon": -73.99
52 | }
53 | }
54 | },
55 |
56 | "$FIELD$": {
57 | top_left: { lat: 40.73, lon: -74.1 },
58 | bottom_right: { lat: 40.73, lon: -74.1 }
59 | },
60 | type: { __one_of: ["memory", "indexed"]},
61 | _cache: {__one_of: [ false, true ]}
62 | },
63 | geo_distance: {
64 | __template: {
65 | distance: 100,
66 | distance_unit: "km",
67 | "FIELD": { lat: 40.73, lon: -74.1 }
68 | },
69 | distance: 100,
70 | distance_unit: { __one_of: [ "km", "miles"]},
71 | distance_type: { __one_of: [ "arc", "plane"]},
72 | optimize_bbox: { __one_of: [ "memory", "indexed", "none"]},
73 | "$FIELD$": { lat: 40.73, lon: -74.1 },
74 | _cache: {__one_of: [ false, true ]}
75 | },
76 | geo_distance_range: {
77 | __template: {
78 | from: 100,
79 | to: 200,
80 | distance_unit: "km",
81 | "FIELD": { lat: 40.73, lon: -74.1 }
82 | },
83 | from: 100,
84 | to: 200,
85 |
86 | distance_unit: { __one_of: [ "km", "miles"]},
87 | distance_type: { __one_of: [ "arc", "plane"]},
88 | include_lower: { __one_of: [ true, false]},
89 | include_upper: { __one_of: [ true, false]},
90 |
91 | "$FIELD$": { lat: 40.73, lon: -74.1 },
92 | _cache: {__one_of: [ false, true ]}
93 | },
94 | geo_polygon: {
95 | __template: {
96 | "FIELD": {
97 | "points": [
98 | { lat: 40.73, lon: -74.1 },
99 | { lat: 40.83, lon: -75.1 }
100 | ]
101 | }
102 | },
103 | "$FIELD$": {
104 | points: [
105 | { lat: 40.73, lon: -74.1 }
106 | ]
107 | },
108 | _cache: {__one_of: [ false, true ]}
109 | },
110 | geo_shape: {
111 | __template: {
112 | "FIELD": {
113 | shape: {
114 | type: "envelope",
115 | coordinates: [
116 | [-45, 45],
117 | [45, -45]
118 | ]
119 | },
120 | "relation": "within"
121 | }
122 | },
123 | "$FIELD$": {
124 | shape: {
125 | type: "",
126 | coordinates: []
127 | },
128 | indexed_shape: {
129 | id: "",
130 | index: "$INDEX$",
131 | type: "$TYPE$",
132 | shape_field_name: "shape"
133 | },
134 | relation: { __one_of: ["within", "intersects", "disjoint"]}
135 | }
136 | },
137 | has_child: {
138 | __template: {
139 | type: "TYPE",
140 | query: {}
141 | },
142 | type: "$TYPE$",
143 | query: {},
144 | _scope: ""
145 | },
146 | has_parent: {
147 | __template: {
148 | type: "TYPE",
149 | query: {}
150 | },
151 | type: "$TYPE$",
152 | query: {},
153 | _scope: ""
154 | },
155 | match_all: { },
156 | missing: {
157 | __template: {
158 | field: "FIELD"
159 | },
160 | existence: { __one_of: [ true, false]},
161 | null_value: { __one_of: [ true, false]},
162 | field: "$FIELD$"
163 | },
164 | not: {
165 | __template: {
166 | filter: {}
167 | },
168 | filter: { __scope_link: ".filter"},
169 | _cache: { __one_of: [ true, false]}
170 | },
171 | numeric_range: {
172 | __template: {
173 | "FIELD": {
174 | from: 10,
175 | to: 20
176 | }
177 | },
178 | from: 1,
179 | to: 20,
180 | include_lower: { __one_of: [ true, false]},
181 | include_upper: { __one_of: [ true, false]}
182 | },
183 | or: {
184 | __template: {
185 | filters: [
186 | {}
187 | ]
188 | },
189 | filters: [
190 | { __scope_link: ".filter" }
191 | ],
192 | _cache: {__one_of: [ false, true ]}
193 | },
194 | prefix: {
195 | __template: {
196 | "FIELD": "VALUE"
197 | },
198 | "$FIELD$": "",
199 | _cache: { __one_of: [ true, false]}
200 | },
201 | query: { __scope_link: ".query"},
202 | fquery: {
203 | __template: {
204 | query: {},
205 | _cache: true
206 | },
207 | query: { __scope_link: ".query"},
208 | _cache: { __one_of: [ true, false]}
209 | },
210 | range: {
211 | __template: {
212 | "FIELD": {
213 | from: 10,
214 | to: 20
215 | }
216 | },
217 | from: 1,
218 | to: 20,
219 | include_lower: { __one_of: [ true, false]},
220 | include_upper: { __one_of: [ true, false]},
221 | _cache: { __one_of: [ false, true ]}
222 | },
223 | script: {
224 | __template: {
225 | script: "SCRIPT",
226 | params: {}
227 | },
228 | script: "",
229 | params: {},
230 | _cache: { __one_of: [ true, false]}
231 | },
232 | term: {
233 | __template: {
234 | "FIELD": "VALUE"
235 | },
236 | "$FIELD$": "",
237 | _cache: { __one_of: [ false, true]}
238 | },
239 | terms: {
240 | __template: { "FIELD": ["VALUE1", "VALUE2"]},
241 | field: [ "$FIELD$"],
242 | execution: { __one_of: [ "plain", "bool", "and", "or", "bool_nocache", "and_nocache", "or_nocache"]},
243 | _cache: { __one_of: [ false, true ]}
244 | },
245 | nested: {
246 | __template: {
247 | path: "path_to_nested_doc",
248 | query: {}
249 | },
250 | query: {},
251 | path: "",
252 | _cache: { __one_of: [ true, false]},
253 | _name: ""
254 | }
255 | });
256 |
--------------------------------------------------------------------------------
/src/history.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | var global = window;
4 |
5 | var history_viewer, history_popup;
6 |
7 | function getHistoryKeys() {
8 | var keys = [];
9 | for (var i = 0; i < localStorage.length; i++) {
10 | var k = localStorage.key(i);
11 | if (k.indexOf("hist_elem") == 0) {
12 | keys.push(k);
13 | }
14 | }
15 |
16 | keys.sort();
17 | keys.reverse();
18 | return keys;
19 | }
20 |
21 | function getHistory() {
22 | var hist_items = [];
23 | $.each(getHistoryKeys(), function (i, key) {
24 | hist_items.push(JSON.parse(localStorage.getItem(key)));
25 | });
26 |
27 | return hist_items;
28 | }
29 |
30 | function getHistoricalServers() {
31 | var servers = {};
32 | $.each(getHistory(), function (i, h) {
33 | servers[h.server] = 1;
34 | });
35 |
36 | var server_list = [];
37 | for (var s in servers) server_list.push(s);
38 |
39 | return server_list;
40 | }
41 |
42 | function populateHistElem(hist_elem) {
43 | var s = hist_elem.method + " " + hist_elem.endpoint + "\n" + (hist_elem.data || "");
44 | history_viewer.setValue(s);
45 | history_viewer.clearSelection();
46 | }
47 |
48 | function applyHistElem(hist_elem) {
49 | var session = sense.editor.getSession();
50 | var pos = sense.editor.getCursorPosition();
51 | var prefix = "";
52 | var suffix = "\n";
53 | if (sense.utils.isStartRequestRow(pos.row)) {
54 | pos.column = 0;
55 | suffix += "\n";
56 | }
57 | else if (sense.utils.isEndRequestRow(pos.row)) {
58 | var line = session.getLine(pos.row);
59 | pos.column = line.length;
60 | prefix = "\n\n";
61 | }
62 | else if (sense.utils.isInBetweenRequestsRow(pos.row)) {
63 | pos.column = 0;
64 | }
65 | else {
66 | pos = sense.utils.nextRequestEnd(pos);
67 | prefix = "\n\n";
68 | }
69 |
70 | var s = prefix + hist_elem.method + " " + hist_elem.endpoint;
71 | if (hist_elem.data) s += "\n" + hist_elem.data;
72 |
73 | s += suffix;
74 |
75 | session.insert(pos, s);
76 | sense.editor.clearSelection();
77 | sense.editor.moveCursorTo(pos.row + prefix.length, 0);
78 | sense.editor.focus();
79 | }
80 |
81 | function init() {
82 |
83 | history_popup = $("#history_popup");
84 |
85 |
86 | history_popup.on('shown', function () {
87 | _gaq.push(['_trackEvent', "history", 'shown']);
88 | $('No history available
').appendTo(history_popup.find(".modal-body"));
89 |
90 | history_viewer = ace.edit("history_viewer");
91 | history_viewer.getSession().setMode("ace/mode/sense");
92 | // history_viewer.setTheme("ace/theme/monokai");
93 | history_viewer.getSession().setFoldStyle('markbeginend');
94 | history_viewer.setReadOnly(true);
95 | history_viewer.renderer.setShowPrintMargin(false);
96 | sense.editor.getSession().setUseWrapMode(true);
97 |
98 | $.each(getHistory(), function (i, hist_elem) {
99 | var li = $(' ');
100 | var disc = hist_elem.endpoint;
101 | var date = moment(hist_elem.time);
102 | if (date.diff(moment(), "days") < -7)
103 | disc += " (" + date.format("MMM D") + ")";
104 | else
105 | disc += " (" + date.fromNow() + ")";
106 |
107 | li.find("span").text(disc);
108 | li.attr("title", disc);
109 |
110 | li.find("a").click(function () {
111 | history_popup.find('.modal-body .nav li').removeClass("active");
112 | li.addClass("active");
113 | populateHistElem(hist_elem);
114 | return false;
115 | });
116 |
117 | li.dblclick(function () {
118 | li.addClass("active");
119 | history_popup.find(".btn-primary").click();
120 | });
121 |
122 | li.hover(function () {
123 | populateHistElem(hist_elem);
124 | return false;
125 | }, function () {
126 | history_popup.find(".modal-body .nav li.active a").click();
127 | });
128 |
129 | li.bind('apply', function () {
130 | _gaq.push(['_trackEvent', "history", 'applied']);
131 | applyHistElem(hist_elem);
132 | });
133 |
134 |
135 | li.appendTo(history_popup.find(".modal-body .nav"));
136 | });
137 |
138 | history_popup.find(".modal-body .nav li:first a").click();
139 |
140 | });
141 |
142 | history_popup.on('hidden', function () {
143 | history_popup.find('.modal-body #history_viewer').remove();
144 | history_popup.find('.modal-body .nav li').remove();
145 | history_viewer = null;
146 | });
147 |
148 | history_popup.find(".btn-primary").click(function () {
149 | history_popup.find(".modal-body .nav li.active").trigger("apply");
150 | });
151 |
152 | history_popup.find("#hist_clear").click(function () {
153 | var keys = getHistoryKeys();
154 | $.each(keys, function (i, k) {
155 | localStorage.removeItem(k);
156 | });
157 | history_popup.find(".modal-body .nav").html("");
158 | history_viewer.getSession().setValue("No history available");
159 | })
160 |
161 | }
162 |
163 | function addToHistory(server, endpoint, method, data) {
164 | var keys = getHistoryKeys();
165 | keys.splice(0, 500); // only maintain most recent X;
166 | $.each(keys, function (i, k) {
167 | localStorage.removeItem(k);
168 | });
169 |
170 | var timestamp = new Date().getTime();
171 | var k = "hist_elem_" + timestamp;
172 | localStorage.setItem(k, JSON.stringify(
173 | { 'time': timestamp, 'server': server, 'endpoint': endpoint, 'method': method, 'data': data }));
174 | }
175 |
176 | function saveCurrentEditorState(server, content) {
177 | var timestamp = new Date().getTime();
178 | localStorage.setItem("editor_state", JSON.stringify(
179 | { 'time': timestamp, 'server': server, 'content': content }));
180 |
181 | }
182 |
183 | function getSavedEditorState(server, content) {
184 | return JSON.parse(localStorage.getItem("editor_state"));
185 | }
186 |
187 | global.sense.history = {
188 | init: init,
189 | addToHistory: addToHistory,
190 | getHistoricalServers: getHistoricalServers,
191 | saveCurrentEditorState: saveCurrentEditorState,
192 | getSavedEditorState: getSavedEditorState
193 | };
194 |
195 | })();
196 |
197 |
198 |
199 |
200 |
201 |
--------------------------------------------------------------------------------
/tests/src/tokenization_tests.js:
--------------------------------------------------------------------------------
1 | var sense = window.sense;
2 | var utils = sense.utils;
3 |
4 | module("Tokenization", {
5 | setup: function () {
6 |
7 | sense.tests = {};
8 | sense.tests.editor_div = $('
').appendTo($('body'));
9 | sense.tests.editor = ace.edit("editor");
10 | ace.require("ace/mode/sense");
11 | sense.tests.editor.getSession().setMode("ace/mode/sense");
12 | sense.tests.editor.getSession().setValue("hello");
13 |
14 | },
15 |
16 | teardown: function () {
17 | sense.tests.editor_div.remove();
18 | sense.tests = {};
19 | }
20 | });
21 |
22 | function tokensAsList(editor) {
23 | var iter = new (ace.require("ace/token_iterator").TokenIterator)(editor.getSession(), 0, 0);
24 | var ret = [];
25 | var t = iter.getCurrentToken();
26 | if (utils.isEmptyToken(t)) t = utils.nextNonEmptyToken(iter);
27 | while (t) {
28 | ret.push({ value: t.value, type: t.type });
29 | t = utils.nextNonEmptyToken(iter);
30 | }
31 |
32 | return ret;
33 | }
34 |
35 | var testCount = 0;
36 |
37 | function token_test(token_list, prefix, data) {
38 | if (data && typeof data != "string") data = JSON.stringify(data, null, 3);
39 | if (data) {
40 | if (prefix) data = prefix + "\n" + data;
41 | } else {
42 | data = prefix;
43 | }
44 |
45 | QUnit.asyncTest("Token test " + testCount++ + " prefix: " + prefix, function () {
46 | var editor = sense.tests.editor;
47 |
48 | utils.updateEditorAndCallWhenUpdated(data, editor, function () {
49 | var tokens = tokensAsList(editor);
50 | var normTokenList = [];
51 | for (var i = 0; i < token_list.length; i++) {
52 | normTokenList.push({ type: token_list[i++], value: token_list[i] });
53 | }
54 |
55 | deepEqual(tokens, normTokenList, "Doc:\n" + data);
56 | start();
57 | });
58 |
59 | });
60 | }
61 |
62 | token_test(
63 | [ "method", "GET", "url.endpoint", "_search" ],
64 | "GET _search"
65 | );
66 |
67 | token_test(
68 | [ "method", "GET", "url.slash", "/", "url.endpoint", "_search" ],
69 | "GET /_search"
70 | );
71 |
72 |
73 | token_test(
74 | [ "method", "GET", "url.endpoint", "_cluster", "url.slash", "/", "url.part" , "nodes" ],
75 | "GET _cluster/nodes"
76 | );
77 |
78 | token_test(
79 | [ "method", "GET", "url.slash", "/", "url.endpoint", "_cluster", "url.slash", "/", "url.part" , "nodes" ],
80 | "GET /_cluster/nodes"
81 | );
82 |
83 |
84 | token_test(
85 | [ "method", "GET", "url.index", "index", "url.slash", "/", "url.endpoint", "_search" ],
86 | "GET index/_search"
87 | );
88 |
89 | token_test(
90 | [ "method", "GET", "url.index", "index" ],
91 | "GET index"
92 | );
93 |
94 | token_test(
95 | [ "method", "GET", "url.index", "index", "url.slash", "/", "url.type", "type" ],
96 | "GET index/type"
97 | );
98 |
99 | token_test(
100 | [ "method", "GET", "url.slash", "/", "url.index", "index", "url.slash", "/", "url.type", "type", "url.slash", "/" ],
101 | "GET /index/type/"
102 | );
103 |
104 | token_test(
105 | [ "method", "GET", "url.index", "index", "url.slash", "/", "url.type", "type", "url.slash", "/", "url.endpoint", "_search" ],
106 | "GET index/type/_search"
107 | );
108 |
109 | token_test(
110 | [ "method", "GET", "url.index", "index", "url.slash", "/", "url.type", "type", "url.slash", "/", "url.endpoint", "_search",
111 | "url.questionmark", "?", "url.param", "value", "url.equal", "=", "url.value", "1"
112 | ],
113 | "GET index/type/_search?value=1"
114 | );
115 |
116 |
117 | token_test(
118 | [ "method", "GET", "url.index", "index", "url.slash", "/", "url.type", "type", "url.slash", "/", "url.id", "1" ],
119 | "GET index/type/1"
120 | );
121 |
122 |
123 | token_test(
124 | [ "method", "GET", "url.slash", "/", "url.index", "index1", "url.comma", ",", "url.index", "index2", "url.slash", "/" ],
125 | "GET /index1,index2/"
126 | );
127 |
128 | token_test(
129 | [ "method", "GET", "url.slash", "/", "url.index", "index1", "url.comma", ",", "url.index", "index2", "url.slash", "/",
130 | "url.endpoint", "_search"],
131 | "GET /index1,index2/_search"
132 | );
133 |
134 | token_test(
135 | [ "method", "GET", "url.index", "index1", "url.comma", ",", "url.index", "index2", "url.slash", "/",
136 | "url.endpoint", "_search"],
137 | "GET index1,index2/_search"
138 | );
139 |
140 | token_test(
141 | [ "method", "GET", "url.slash", "/", "url.index", "index1", "url.comma", ",", "url.index", "index2" ],
142 | "GET /index1,index2"
143 | );
144 |
145 | token_test(
146 | [ "method", "GET", "url.index", "index1", "url.comma", ",", "url.index", "index2" ],
147 | "GET index1,index2"
148 | );
149 |
150 | token_test(
151 | [ "method", "GET", "url.slash", "/", "url.index", "index1", "url.comma", "," ],
152 | "GET /index1,"
153 | );
154 |
155 |
156 | token_test(
157 | [ "method", "PUT", "url.slash", "/", "url.index", "index", "url.slash", "/" ],
158 | "PUT /index/"
159 | );
160 |
161 | token_test(
162 | [ "method", "PUT", "url.slash", "/", "url.index", "index" ],
163 | "PUT /index"
164 | );
165 |
166 | token_test(
167 | [ "method", "PUT", "url.slash", "/", "url.index", "index1", "url.comma", ",", "url.index", "index2",
168 | "url.slash", "/", "url.type", "type1", "url.comma", ",", "url.type", "type2"],
169 | "PUT /index1,index2/type1,type2"
170 | );
171 |
172 | token_test(
173 | [ "method", "PUT", "url.slash", "/", "url.index", "index1",
174 | "url.slash", "/", "url.type", "type1", "url.comma", ",", "url.type", "type2", "url.comma", ","],
175 | "PUT /index1/type1,type2,"
176 | );
177 |
178 | token_test(
179 | [ "method", "PUT", "url.index", "index1", "url.comma", ",", "url.index", "index2",
180 | "url.slash", "/", "url.type", "type1", "url.comma", ",", "url.type", "type2", "url.slash", "/",
181 | "url.id", "1234"],
182 | "PUT index1,index2/type1,type2/1234"
183 | );
184 |
185 |
186 | token_test(
187 | [ "method", "POST", "url.endpoint", "_search", "paren.lparen", "{", "variable", '"q"', "punctuation.colon", ":",
188 | "paren.lparen", "{", "paren.rparen", "}", "paren.rparen", "}"
189 | ],
190 | 'POST _search\n' +
191 | '{\n' +
192 | ' "q": {}\n' +
193 | ' \n' +
194 | '}'
195 | );
196 |
197 | function statesAsList(editor) {
198 | var ret = [];
199 | var session = editor.getSession();
200 | var maxLine = session.getLength();
201 | for (var row = 0; row < maxLine; row++) ret.push(session.getState(row));
202 |
203 | return ret;
204 | }
205 |
206 |
207 | function states_test(states_list, prefix, data) {
208 | if (data && typeof data != "string") data = JSON.stringify(data, null, 3);
209 | if (data) {
210 | if (prefix) data = prefix + "\n" + data;
211 | } else {
212 | data = prefix;
213 | }
214 |
215 | QUnit.asyncTest("States test " + testCount++ + " prefix: " + prefix, function () {
216 | var editor = global.sense.tests.editor;
217 |
218 | utils.updateEditorAndCallWhenUpdated(data, editor, function () {
219 | var modes = statesAsList(editor);
220 | deepEqual(modes, states_list, "Doc:\n" + data);
221 |
222 | start();
223 | });
224 |
225 | });
226 | }
227 |
228 |
229 | function n(name) {
230 | return { name: name};
231 | }
232 | function nd(name, depth) {
233 | return { name: name, depth: depth };
234 | }
235 |
236 | states_test(
237 | [n("start"), nd("json", 1), nd("json", 1), nd("start", 0) ],
238 | 'POST _search\n' +
239 | '{\n' +
240 | ' "query": { "match_all": {} }\n' +
241 | '}'
242 | );
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Sense - a JSON aware interface to ElasticSearch
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | Server
14 |
15 |
18 |
20 | Help
21 | History
22 |
23 |
24 |
25 |
26 |
27 |
GET _search
28 | {
29 | "query": { "match_all": {} }
30 | }
31 |
32 |
{}
33 |
45 |
46 |
47 |
48 |
49 |
95 |
112 |
113 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/src/mappings.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | var global = window;
4 |
5 | var currentServer;
6 | var per_index_types = {};
7 | var per_alias_indexes = [];
8 |
9 |
10 | function expandAliases(indicesOrAliases) {
11 | // takes a list of indices or aliases or a string which may be either and returns a list of indices
12 | // returns a list for multiple values or a string for a single.
13 |
14 | if (!indicesOrAliases) return indicesOrAliases;
15 |
16 | if (typeof indicesOrAliases === "string") indicesOrAliases = [indicesOrAliases];
17 | indicesOrAliases = $.map(indicesOrAliases, function (iOrA) {
18 | if (per_alias_indexes[iOrA]) return per_alias_indexes[iOrA];
19 | return [iOrA];
20 | });
21 | var ret = [].concat.apply([], indicesOrAliases);
22 | ret.sort();
23 | var last;
24 | ret = $.map(ret, function (v) {
25 | var r = last == v ? null : v;
26 | last = v;
27 | return r;
28 | });
29 | return ret.length > 1 ? ret : ret[0];
30 | }
31 |
32 | function getFields(indices, types) {
33 | // get fields for indices and types. Both can be a list, a string or null (meaning all).
34 | var ret = [];
35 | indices = expandAliases(indices);
36 | if (typeof indices == "string") {
37 |
38 | var type_dict = per_index_types[indices];
39 | if (!type_dict) return [];
40 |
41 | if (typeof types == "string") {
42 | var f = type_dict[types];
43 | ret = f ? f : [];
44 | }
45 | else {
46 | // filter what we need
47 | $.each(type_dict, function (type, fields) {
48 | if (!types || types.length == 0 || $.inArray(type, types) != -1)
49 | ret.push(fields);
50 | });
51 |
52 | ret = [].concat.apply([], ret);
53 | }
54 | }
55 | else {
56 | // multi index mode.
57 | $.each(per_index_types, function (index) {
58 | if (!indices || indices.length == 0 || $.inArray(index, indices) != -1)
59 | ret.push(getFields(index, types));
60 | });
61 | ret = [].concat.apply([], ret);
62 | }
63 |
64 | return ret;
65 | }
66 |
67 | function getTypes(indices) {
68 | var ret = [];
69 | indices = expandAliases(indices);
70 | if (typeof indices == "string") {
71 | var type_dict = per_index_types[indices];
72 | if (!type_dict) return [];
73 |
74 | // filter what we need
75 | $.each(type_dict, function (type, fields) {
76 | ret.push(type);
77 | });
78 |
79 | }
80 | else {
81 | // multi index mode.
82 | $.each(per_index_types, function (index) {
83 | if (!indices || $.inArray(index, indices) != -1)
84 | ret.push(getTypes(index));
85 | });
86 | ret = [].concat.apply([], ret);
87 | }
88 |
89 | return ret.filter(function (v, i, a) {
90 | return a.indexOf(v) == i
91 | }); // dedupe array;
92 |
93 | }
94 |
95 |
96 | function getIndices(include_aliases) {
97 | var ret = [];
98 | $.each(per_index_types, function (index) {
99 | ret.push(index);
100 | });
101 | if (typeof include_aliases === "undefined" ? true : include_aliases) {
102 | $.each(per_alias_indexes, function (alias) {
103 | ret.push(alias);
104 | });
105 | }
106 | return ret;
107 | }
108 |
109 | function getFieldNamesFromFieldMapping(field_name, field_mapping) {
110 | if (field_mapping['enabled'] == false) return [];
111 |
112 |
113 | function applyPathSettings(nested_field_names) {
114 | var path_type = field_mapping['path'] || "full";
115 | if (path_type == "full") {
116 | return $.map(nested_field_names, function (f) {
117 | return field_name + "." + f;
118 | });
119 | }
120 | return nested_field_names;
121 | }
122 |
123 | if (field_mapping["properties"]) {
124 | // derived object type
125 | var nested_fields = getFieldNamesFromTypeMapping(field_mapping);
126 | return applyPathSettings(nested_fields);
127 | }
128 |
129 | if (field_mapping['type'] == 'multi_field') {
130 | var nested_fields = $.map(field_mapping['fields'], function (field_mapping, field_name) {
131 | return getFieldNamesFromFieldMapping(field_name, field_mapping);
132 | });
133 |
134 | return applyPathSettings(nested_fields);
135 | }
136 |
137 | if (field_mapping["index_name"]) return [field_mapping["index_name"]];
138 |
139 | return [field_name];
140 | }
141 |
142 | function getFieldNamesFromTypeMapping(type_mapping) {
143 | var field_list =
144 | $.map(type_mapping['properties'], function (field_mapping, field_name) {
145 | return getFieldNamesFromFieldMapping(field_name, field_mapping);
146 | });
147 |
148 | // deduping
149 | var last = undefined;
150 | field_list.sort();
151 | return $.map(field_list, function (f) {
152 | var r = (f === last) ? null : f;
153 | last = f;
154 | return r;
155 | });
156 | }
157 |
158 | function loadMappings(mappings) {
159 | per_index_types = {};
160 | $.each(mappings, function (index, index_mapping) {
161 | var normalized_index_mappings = {};
162 | $.each(index_mapping, function (type_name, type_mapping) {
163 | var field_list = getFieldNamesFromTypeMapping(type_mapping);
164 | normalized_index_mappings[type_name] = field_list;
165 | });
166 | per_index_types[index] = normalized_index_mappings;
167 | });
168 | }
169 |
170 | function loadAliases(aliases) {
171 | per_alias_indexes = {}
172 | $.each(aliases, function (index, index_aliases) {
173 | $.each(index_aliases.aliases, function (alias) {
174 | if (alias === index) return; // alias which is identical to index means no index.
175 | var cur_aliases = per_alias_indexes[alias];
176 | if (!cur_aliases) {
177 | cur_aliases = [];
178 | per_alias_indexes[alias] = cur_aliases;
179 | }
180 | cur_aliases.push(index);
181 | });
182 | });
183 |
184 | per_alias_indexes['_all'] = getIndices(false);
185 | }
186 |
187 | function clear() {
188 | per_index_types = {};
189 | per_alias_indexes = {};
190 | }
191 |
192 | function retrieveMappingFromServer() {
193 | if (!currentServer) return;
194 | callES(currentServer, "_mapping", "GET", null, function (data, status, xhr) {
195 | loadMappings(data);
196 | });
197 | callES(currentServer, "_aliases", "GET", null, function (data, status, xhr) {
198 | loadAliases(data);
199 | });
200 |
201 | }
202 |
203 | function notifyServerChange(newServer) {
204 | if (newServer.indexOf("://") < 0) newServer = "http://" + newServer;
205 | newServer = newServer.trim("/");
206 | if (newServer === currentServer) return; // already have it.
207 | currentServer = newServer;
208 | retrieveMappingFromServer();
209 | }
210 |
211 | function mapping_retriever() {
212 | retrieveMappingFromServer();
213 | setTimeout(function () {
214 | mapping_retriever();
215 | }, 60000);
216 | }
217 |
218 | mapping_retriever();
219 |
220 | if (!global.sense) global.sense = {};
221 | global.sense.mappings = {};
222 | global.sense.mappings.getFields = getFields;
223 | global.sense.mappings.getIndices = getIndices;
224 | global.sense.mappings.getTypes = getTypes;
225 | global.sense.mappings.loadMappings = loadMappings;
226 | global.sense.mappings.loadAliases = loadAliases;
227 | global.sense.mappings.expandAliases = expandAliases;
228 | global.sense.mappings.clear = clear;
229 | global.sense.mappings.notifyServerChange = notifyServerChange;
230 |
231 | })();
--------------------------------------------------------------------------------
/kb/query.js:
--------------------------------------------------------------------------------
1 | SPAN_QUERIES = {
2 | // TODO add one_of for objects
3 | span_first: {__scope_link: ".query.span_first"},
4 | span_near: {__scope_link: ".query.span_near"},
5 | span_or: {__scope_link: ".query.span_or"},
6 | span_not: {__scope_link: ".query.span_not"},
7 | span_term: {__scope_link: ".query.span_term"}
8 | };
9 |
10 | sense.kb.addGlobalAutocompleteRules("query", {
11 | match: { __template: { "FIELD": "TEXT" },
12 | "$FIELD$": {
13 | "query": "",
14 | "operator": { __one_of: ["and" , "or"]},
15 | "type": { __one_of: [ "phrase", "phrase_prefix", "boolean"]},
16 | "max_expansions": 10,
17 | "analyzer": "",
18 | "fuzziness": 1.0,
19 | "prefix_length": 1
20 | } },
21 | match_phrase: { __template: { "FIELD": "PHRASE" },
22 | "$FIELD$": {
23 | query: "",
24 | analyzer: ""
25 | } },
26 | match_phrase_prefix: { __template: { "FIELD": "PREFIX" },
27 | "$FIELD$": {
28 | query: "",
29 | analyzer: "",
30 | max_expansions: 10,
31 | prefix_length: 1,
32 | fuzziness: 0.1
33 | } },
34 | multi_match: { __template: { "query": "", "fields": [] },
35 | query: "",
36 | fields: ["$FIELD$"],
37 | use_dis_max: { __template: true, __one_of: [ true, false ]},
38 | tie_breaker: 0.0
39 | },
40 | bool: {
41 | must: [
42 | { __scope_link: "GLOBAL.query"}
43 | ],
44 | must_not: [
45 | { __scope_link: "GLOBAL.query"}
46 | ],
47 | should: [
48 | { __scope_link: "GLOBAL.query" }
49 | ],
50 | minimum_number_should_match: 1,
51 | boost: 1.0
52 | },
53 | boosting: {
54 | positive: { __scope_link: ".query" },
55 | negative: { __scope_link: ".query" },
56 | negative_boost: 0.2
57 | },
58 | ids: { type: "", values: [] },
59 | custom_score: {
60 | __template: { query: {}, script: ""},
61 | query: {},
62 | script: "",
63 | params: {},
64 | lang: "mvel"
65 | },
66 | custom_boost_factor: {
67 | __template: { query: {}, boost_factor: 1.1 },
68 | query: {},
69 | boost_factor: 1.1
70 | },
71 | constant_score: {
72 | __template: { filter: {}, boost: 1.2 },
73 | query: {},
74 | filter: {},
75 | boost: 1.2
76 | },
77 | dis_max: {
78 | __template: { tie_breaker: 0.7, boost: 1.2, queries: []},
79 | tie_breaker: 0.7,
80 | boost: 1.2,
81 | queries: [
82 | { __scope_link: ".query"}
83 | ]
84 | },
85 | field: {
86 | "$FIELD$": {
87 | query: "", boost: 2.0,
88 | enable_position_increments: { __template: false, __one_of: [ true, false ]}
89 | } },
90 | filtered: {
91 | __template: {
92 | query: {},
93 | filter: {}
94 | },
95 | query: {},
96 | filter: {}
97 | },
98 | fuzzy_like_this: {
99 | fields: [],
100 | like_text: "",
101 | max_query_terms: 12
102 | },
103 | flt: {
104 | __scope_link: ".query.fuzzy_like_this"
105 | },
106 | fuzzy: {
107 | "$FIELD$": {
108 | "value": "",
109 | "boost": 1.0,
110 | "min_similarity": 0.5,
111 | "prefix_length": 0
112 | }
113 | },
114 | has_child: {
115 | "type": "$TYPE$",
116 | "score_type": { __one_of: ["none", "max", "sum", "avg"]},
117 | "_scope": "",
118 | "query": {
119 | }
120 | },
121 | has_parent: {
122 | "parent_type": "$TYPE$",
123 | "score_type": { __one_of: ["none", "score"]},
124 | "_scope": "",
125 | "query": {
126 | }
127 | },
128 | match_all: {},
129 | more_like_this: {
130 | __template: {
131 | "fields": ["FIELD"],
132 | "like_text": "text like this one",
133 | "min_term_freq": 1,
134 | "max_query_terms": 12
135 | },
136 | fields: [ "$FIELD$ "],
137 | like_text: "",
138 | percent_terms_to_match: 0.3,
139 | min_term_freq: 2,
140 | max_query_terms: 25,
141 | stop_words: [""],
142 | min_doc_freq: 5,
143 | max_doc_freq: 100,
144 | min_word_len: 0,
145 | max_word_len: 0,
146 | boost_terms: 1,
147 | boost: 1.0,
148 | analyzer: ""
149 | },
150 | more_like_this_field: {
151 | __template: {
152 | "FIELD": {
153 | "like_text": "text like this one",
154 | "min_term_freq": 1,
155 | "max_query_terms": 12
156 | } },
157 | "$FIELD$": {
158 | like_text: "",
159 | percent_terms_to_match: 0.3,
160 | min_term_freq: 2,
161 | max_query_terms: 25,
162 | stop_words: [""],
163 | min_doc_freq: 5,
164 | max_doc_freq: 100,
165 | min_word_len: 0,
166 | max_word_len: 0,
167 | boost_terms: 1,
168 | boost: 1.0,
169 | analyzer: ""
170 | }
171 | },
172 | prefix: {
173 | __template: {
174 | "FIELD": { "value": "" }
175 | },
176 | "$FIELD$": {
177 | value: "",
178 | boost: 1.0
179 | }
180 | },
181 | query_string: {
182 | __template: {
183 | "default_field": "FIELD",
184 | "query": "this AND that OR thus"
185 | },
186 | query: "",
187 | default_field: "$FIELD$",
188 | fields: ["$FIELD$"],
189 | default_operator: { __one_of: ["OR", "AND"] },
190 | analyzer: "",
191 | allow_leading_wildcard: { __one_of: [ true, false]},
192 | lowercase_expanded_terms: { __one_of: [ true, false]},
193 | enable_position_increments: { __one_of: [ true, false]},
194 | fuzzy_max_expansions: 50,
195 | fuzzy_min_sim: 0.5,
196 | fuzzy_prefix_length: 0,
197 | phrase_slop: 0,
198 | boost: 1.0,
199 | analyze_wildcard: { __one_of: [ false, true ]},
200 | auto_generate_phrase_queries: { __one_of: [ false, true ]},
201 | minimum_should_match: "20%",
202 | lenient: { __one_of: [ false, true ]},
203 | use_dis_max: { __one_of: [ true, false]},
204 | tie_breaker: 0
205 | },
206 | range: {
207 | __template: {
208 | "FIELD": {
209 | from: 10,
210 | to: 20
211 | }
212 | },
213 | "$FIELD$": {
214 | __template: { from: 10, to: 20},
215 | from: 1,
216 | to: 20,
217 | include_lower: { __one_of: [ true, false]},
218 | include_upper: { __one_of: [ true, false]},
219 | boost: 1.0
220 | }
221 | },
222 | span_first: {
223 | __template: {
224 | "match": {
225 | "span_term": { "FIELD": "VALUE" }
226 | },
227 | "end": 3
228 | },
229 | match: SPAN_QUERIES
230 | },
231 | span_near: {
232 | __template: {
233 | "clauses": [
234 | { span_term: { "FIELD": { "value": "VALUE"} } }
235 | ],
236 | slop: 12,
237 | in_order: false
238 | },
239 | clauses: [
240 | SPAN_QUERIES
241 | ],
242 | slop: 12,
243 | in_order: {__one_of: [ false, true ]},
244 | collect_payloads: {__one_of: [ false, true ]}
245 | },
246 | span_term: {
247 | __template: { "FIELD": { "value": "VALUE"}},
248 | "$FIELD$": {
249 | value: "",
250 | boost: 2.0
251 | }
252 | },
253 | span_not: {
254 | __template: {
255 | include: {
256 | span_term: { "FIELD": { "value": "VALUE"} }
257 | },
258 | exclude: {
259 | span_term: { "FIELD": { "value": "VALUE"} }
260 | }
261 | },
262 | include: SPAN_QUERIES,
263 | exclude: SPAN_QUERIES
264 | },
265 | span_or: {
266 | __template: {
267 | clauses: [
268 | { span_term: { "FIELD": { "value": "VALUE"} } }
269 | ]
270 | },
271 | clauses: [
272 | SPAN_QUERIES
273 | ]
274 | },
275 | term: {
276 | __template: { "FIELD": { value: "VALUE" }},
277 | "$FIELD$": {
278 | value: "",
279 | boost: 2.0
280 | }
281 | },
282 | terms: {
283 | __template: {
284 | "FIELD": [ "VALUE1", "VALUE2"]
285 | },
286 | "$FIELD$": [ "" ],
287 | minimum_match: 1
288 | },
289 | top_children: {
290 | __template: {
291 | type: "CHILD_TYPE",
292 | query: {}
293 | },
294 | type: "$CHILD_TYPE$",
295 | query: { },
296 | score: { __one_of: [ "max", "sum", "avg"] },
297 | factor: 5,
298 | incremental_factor: 2
299 | },
300 | wildcard: {
301 | __template: {
302 | "FIELD": { value: "VALUE"}
303 | },
304 | "$FIELD$": { value: "", boost: 2.0 }
305 | },
306 | nested: {
307 | __template: {
308 | path: "path_to_nested_doc",
309 | query: {}
310 | },
311 | path: "",
312 | query: {},
313 | filter: {},
314 | score_mode: { __one_of: ["avg", "total", "max", "none"]}
315 | },
316 | custom_filters_score: {
317 | __template: {
318 | query: {},
319 | filters: [
320 | {
321 | filter: {}
322 | }
323 | ]
324 | },
325 | query: {},
326 | filters: [
327 | { filter: {}, boost: 2.0, script: ""}
328 | ],
329 | score_mode: { __one_of: [ "first", "min", "max", "total", "avg", "multiply"] },
330 | max_boost: 2.0,
331 | params: {},
332 | lang: ""
333 | },
334 | indices: {
335 | __template: {
336 | indices: ["INDEX1", "INDEX2"],
337 | query: {}
338 | },
339 | indices: ["$INDEX$"],
340 | query: {},
341 | no_match_query: { __scope_link: ".query"}
342 | },
343 | geo_shape: {
344 | __template: {
345 | location: {},
346 | relation: "within"
347 | },
348 | __scope_link: ".filter.geo_shape"
349 | }
350 |
351 | });
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | var global = window;
4 | if (!global.sense)
5 | global.sense = {};
6 |
7 | var ns = {};
8 | global.sense.utils = ns;
9 |
10 | var sense = global.sense;
11 |
12 | ROW_PARSE_MODE = {
13 | REQUEST_START: 2,
14 | IN_REQUEST: 4,
15 | MULTI_DOC_CUR_DOC_END: 8,
16 | REQUEST_END: 16,
17 | BETWEEN_REQUESTS: 32
18 | };
19 |
20 | getRowParseMode = function (row, editor) {
21 | editor = editor || sense.editor;
22 | if (row == null || typeof row == "undefined") row = editor.getCursorPosition().row;
23 |
24 | var session = editor.getSession();
25 | if (row >= session.getLength()) return ROW_PARSE_MODE.BETWEEN_REQUESTS;
26 | var mode = (session.getState(row) || {}).name;
27 | if (!mode)
28 | return ROW_PARSE_MODE.BETWEEN_REQUESTS; // shouldn't really happen
29 |
30 |
31 | if (mode != "start") return ROW_PARSE_MODE.IN_REQUEST;
32 | var line = (session.getLine(row) || "").trim();
33 | if (!line) return ROW_PARSE_MODE.BETWEEN_REQUESTS; // empty line waiting for a new req to start
34 |
35 | if (line.indexOf("}", line.length - 1) >= 0) {
36 | // check for a multi doc request (must start a new json doc immediately after this one end.
37 | row++;
38 | if (row < session.getLength()) {
39 | line = (session.getLine(row) || "").trim();
40 | if (line.indexOf("{") == 0) { // next line is another doc in a multi doc
41 | return ROW_PARSE_MODE.MULTI_DOC_CUR_DOC_END | ROW_PARSE_MODE.IN_REQUEST;
42 | }
43 |
44 | }
45 | return ROW_PARSE_MODE.REQUEST_END | ROW_PARSE_MODE.MULTI_DOC_CUR_DOC_END; // end of request
46 | }
47 |
48 | // check for single line requests
49 | row++;
50 | if (row >= session.getLength()) {
51 | return ROW_PARSE_MODE.REQUEST_START | ROW_PARSE_MODE.REQUEST_END;
52 | }
53 | line = (session.getLine(row) || "").trim();
54 | if (line.indexOf("{") != 0) { // next line is another request
55 | return ROW_PARSE_MODE.REQUEST_START | ROW_PARSE_MODE.REQUEST_END;
56 | }
57 |
58 | return ROW_PARSE_MODE.REQUEST_START;
59 | };
60 |
61 | function rowPredicate(row, editor, value) {
62 | var mode = getRowParseMode(row, editor);
63 | return (mode & value) > 0;
64 | }
65 |
66 | ns.isEndRequestRow = function (row, editor) {
67 | return rowPredicate(row, editor, ROW_PARSE_MODE.REQUEST_END);
68 | };
69 |
70 | ns.isRequestEdge = function (row, editor) {
71 | return rowPredicate(row, editor, ROW_PARSE_MODE.REQUEST_END | ROW_PARSE_MODE.REQUEST_START);
72 | };
73 |
74 |
75 | ns.isStartRequestRow = function (row, editor) {
76 | return rowPredicate(row, editor, ROW_PARSE_MODE.REQUEST_START);
77 | };
78 |
79 | ns.isInBetweenRequestsRow = function (row, editor) {
80 | return rowPredicate(row, editor, ROW_PARSE_MODE.BETWEEN_REQUESTS);
81 | };
82 |
83 | ns.isInRequestsRow = function (row, editor) {
84 | return rowPredicate(row, editor, ROW_PARSE_MODE.IN_REQUEST);
85 | };
86 |
87 | ns.isMultiDocDocEndRow = function (row, editor) {
88 | return rowPredicate(row, editor, ROW_PARSE_MODE.MULTI_DOC_CUR_DOC_END);
89 | };
90 |
91 |
92 | ns.iterForCurrentLoc = function (editor) {
93 | editor = editor || sense.editor;
94 | var pos = editor.getCursorPosition();
95 | return ns.iterForPosition(pos.row, pos.column, editor);
96 | };
97 |
98 | ns.iterForPosition = function (row, column, editor) {
99 | editor = editor || sense.editor;
100 | return new (ace.require("ace/token_iterator").TokenIterator)(editor.getSession(), row, column);
101 | };
102 |
103 | ns.isEmptyToken = function (tokenOrTokenIter) {
104 | var token = tokenOrTokenIter && tokenOrTokenIter.getCurrentToken ? tokenOrTokenIter.getCurrentToken() : tokenOrTokenIter;
105 | return !token || token.type == "whitespace"
106 | };
107 |
108 | ns.isUrlOrMethodToken = function (tokenOrTokenIter) {
109 | var t = tokenOrTokenIter.getCurrentToken ? tokenOrTokenIter.getCurrentToken() : tokenOrTokenIter;
110 | return t && t.type && (t.type == "method" || t.type.indexOf("url") == 0);
111 | };
112 |
113 |
114 | ns.nextNonEmptyToken = function (tokenIter) {
115 | var t = tokenIter.stepForward();
116 | while (t && ns.isEmptyToken(t)) t = tokenIter.stepForward();
117 | return t;
118 | };
119 |
120 | ns.prevNonEmptyToken = function (tokenIter) {
121 | var t = tokenIter.stepBackward();
122 | // empty rows return null token.
123 | while ((t || tokenIter.getCurrentTokenRow() > 0) && ns.isEmptyToken(t)) t = tokenIter.stepBackward();
124 | return t;
125 | };
126 |
127 | ns.prevRequestStart = function (pos, editor) {
128 | editor = editor || sense.editor;
129 | pos = pos || editor.getCursorPosition();
130 | var curRow = pos.row;
131 | while (curRow > 0 && !ns.isStartRequestRow(curRow, editor)) curRow--;
132 |
133 | return { row: curRow, column: 0};
134 | };
135 |
136 | ns.nextRequestEnd = function (pos, editor) {
137 | editor = editor || sense.editor;
138 | pos = pos || editor.getCursorPosition();
139 | var session = editor.getSession();
140 | var curRow = pos.row;
141 | var maxLines = session.getLength();
142 | for (; curRow < maxLines - 1; curRow++) {
143 | var curRowMode = getRowParseMode(curRow, editor);
144 | if ((curRowMode & ROW_PARSE_MODE.REQUEST_END) > 0) break;
145 | if (curRow != pos.row && (curRowMode & ROW_PARSE_MODE.REQUEST_START) > 0) break;
146 | }
147 |
148 | var column = (session.getLine(curRow) || "").length;
149 |
150 | return { row: curRow, column: column};
151 | };
152 |
153 | ns.nextDataDocEnd = function (pos, editor) {
154 | editor = editor || sense.editor;
155 | pos = pos || editor.getCursorPosition();
156 | var session = editor.getSession();
157 | var curRow = pos.row;
158 | var maxLines = session.getLength();
159 | for (; curRow < maxLines - 1; curRow++) {
160 | var curRowMode = getRowParseMode(curRow, editor);
161 | if ((curRowMode & ROW_PARSE_MODE.REQUEST_END) > 0) {
162 | break;
163 | }
164 | if ((curRowMode & ROW_PARSE_MODE.MULTI_DOC_CUR_DOC_END) > 0) break;
165 | if (curRow != pos.row && (curRowMode & ROW_PARSE_MODE.REQUEST_START) > 0) break;
166 | }
167 |
168 | var column = (session.getLine(curRow) || "").length;
169 |
170 | return { row: curRow, column: column };
171 | };
172 |
173 |
174 | ns.getCurrentRequestRange = function (editor) {
175 | if (ns.isInBetweenRequestsRow(null, editor)) return null;
176 |
177 | var reqStart = ns.prevRequestStart(null, editor);
178 | var reqEnd = ns.nextRequestEnd(reqStart, editor);
179 | return new (ace.require("ace/range").Range)(
180 | reqStart.row, reqStart.column,
181 | reqEnd.row, reqEnd.column
182 | );
183 | };
184 |
185 | ns.getCurrentRequest = function (editor) {
186 | editor = editor || sense.editor;
187 |
188 | if (ns.isInBetweenRequestsRow(null, editor)) return null;
189 |
190 | var request = {
191 | method: "",
192 | data: [],
193 | url: null
194 | };
195 |
196 | var currentReqRange = ns.getCurrentRequestRange(editor);
197 |
198 | var pos = currentReqRange.start;
199 | var tokenIter = ns.iterForPosition(pos.row, pos.column, editor);
200 | var t = tokenIter.getCurrentToken();
201 | request.method = t.value;
202 | t = ns.nextNonEmptyToken(tokenIter);
203 | if (!t || t.type == "method") return null;
204 | request.url = "";
205 | while (t && t.type && t.type.indexOf("url") == 0) {
206 | request.url += t.value;
207 | t = tokenIter.stepForward();
208 | }
209 |
210 | var bodyStartRow = (t ? 0 : 1) + tokenIter.getCurrentTokenRow(); // artificially increase end of docs.
211 | var bodyStartColumn = 0;
212 | while (bodyStartRow < currentReqRange.end.row ||
213 | (bodyStartRow == currentReqRange.end.row &&
214 | bodyStartColumn < currentReqRange.end.column
215 | )) {
216 | dataEndPos = ns.nextDataDocEnd({ row: bodyStartRow, column: bodyStartColumn}, editor);
217 | var bodyRange = new (ace.require("ace/range").Range)(
218 | bodyStartRow, bodyStartColumn,
219 | dataEndPos.row, dataEndPos.column
220 | );
221 | var data = editor.getSession().getTextRange(bodyRange);
222 | request.data.push(data.trim());
223 | bodyStartRow = dataEndPos.row + 1;
224 | bodyStartColumn = 0;
225 | }
226 | return request;
227 | };
228 |
229 | ns.textFromRequest = function (request) {
230 | var data = request.data;
231 | if (typeof data != "string") {
232 | data = data.join("\n");
233 | }
234 | return request.method + " " + request.url + "\n" + data;
235 | };
236 |
237 | ns.replaceCurrentRequest = function (newRequest, curRequestRange) {
238 | if (!curRequestRange) curRequestRange = ns.getCurrentRequestRange();
239 | var text = ns.textFromRequest(newRequest);
240 | if (curRequestRange) {
241 | sense.editor.getSession().replace(curRequestRange, text);
242 | }
243 | else {
244 | // just insert where we are
245 | sense.editor.insert(text);
246 | }
247 | };
248 |
249 | ns.getUrlParam = function (name) {
250 | name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
251 | var regex = new RegExp("[\\?&]" + name + "=([^]*)"),
252 | results = regex.exec(location.search);
253 | return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
254 | };
255 |
256 | ns.isTokenizationStable = function (editor) {
257 | editor = editor || sense.editor;
258 | return !editor.getSession().bgTokenizer.running;
259 | };
260 |
261 | ns.updateEditorAndCallWhenUpdated = function (data, editor, callback) {
262 | editor = editor || sense.editor;
263 | var session = editor.getSession();
264 |
265 | function mycallback() {
266 | session.removeListener(mycallback);
267 | if (session.bgTokenizer.running) {
268 | setTimeout(mycallback, 50); // wait
269 | return;
270 | }
271 | callback();
272 | }
273 |
274 | session.on('tokenizerUpdate', mycallback);
275 | session.setValue(data);
276 | }
277 |
278 | })();
--------------------------------------------------------------------------------
/lib/moment.min.js:
--------------------------------------------------------------------------------
1 | // moment.js
2 | // version : 1.7.2
3 | // author : Tim Wood
4 | // license : MIT
5 | // momentjs.com
6 | (function(a){function E(a,b,c,d){var e=c.lang();return e[a].call?e[a](c,d):e[a][b]}function F(a,b){return function(c){return K(a.call(this,c),b)}}function G(a){return function(b){var c=a.call(this,b);return c+this.lang().ordinal(c)}}function H(a,b,c){this._d=a,this._isUTC=!!b,this._a=a._a||null,this._lang=c||!1}function I(a){var b=this._data={},c=a.years||a.y||0,d=a.months||a.M||0,e=a.weeks||a.w||0,f=a.days||a.d||0,g=a.hours||a.h||0,h=a.minutes||a.m||0,i=a.seconds||a.s||0,j=a.milliseconds||a.ms||0;this._milliseconds=j+i*1e3+h*6e4+g*36e5,this._days=f+e*7,this._months=d+c*12,b.milliseconds=j%1e3,i+=J(j/1e3),b.seconds=i%60,h+=J(i/60),b.minutes=h%60,g+=J(h/60),b.hours=g%24,f+=J(g/24),f+=e*7,b.days=f%30,d+=J(f/30),b.months=d%12,c+=J(d/12),b.years=c,this._lang=!1}function J(a){return a<0?Math.ceil(a):Math.floor(a)}function K(a,b){var c=a+"";while(c.length70?1900:2e3);break;case"YYYY":c[0]=~~Math.abs(b);break;case"a":case"A":d.isPm=(b+"").toLowerCase()==="pm";break;case"H":case"HH":case"h":case"hh":c[3]=~~b;break;case"m":case"mm":c[4]=~~b;break;case"s":case"ss":c[5]=~~b;break;case"S":case"SS":case"SSS":c[6]=~~(("0."+b)*1e3);break;case"Z":case"ZZ":d.isUTC=!0,e=(b+"").match(x),e&&e[1]&&(d.tzh=~~e[1]),e&&e[2]&&(d.tzm=~~e[2]),e&&e[0]==="+"&&(d.tzh=-d.tzh,d.tzm=-d.tzm)}b==null&&(c[8]=!1)}function W(a,b){var c=[0,0,1,0,0,0,0],d={tzh:0,tzm:0},e=b.match(k),f,g;for(f=0;f0,j[4]=c,Z.apply({},j)}function _(a,c){b.fn[a]=function(a){var b=this._isUTC?"UTC":"";return a!=null?(this._d["set"+b+c](a),this):this._d["get"+b+c]()}}function ab(a){b.duration.fn[a]=function(){return this._data[a]}}function bb(a,c){b.duration.fn["as"+a]=function(){return+this/c}}var b,c="1.7.2",d=Math.round,e,f={},g="en",h=typeof module!="undefined"&&module.exports,i="months|monthsShort|weekdays|weekdaysShort|weekdaysMin|longDateFormat|calendar|relativeTime|ordinal|meridiem".split("|"),j=/^\/?Date\((\-?\d+)/i,k=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|zz?|ZZ?|.)/g,l=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?)/g,m=/([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi,n=/\d\d?/,o=/\d{1,3}/,p=/\d{3}/,q=/\d{1,4}/,r=/[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+/i,s=/Z|[\+\-]\d\d:?\d\d/i,t=/T/i,u=/^\s*\d{4}-\d\d-\d\d(T(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,v="YYYY-MM-DDTHH:mm:ssZ",w=[["HH:mm:ss.S",/T\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/T\d\d:\d\d:\d\d/],["HH:mm",/T\d\d:\d\d/],["HH",/T\d\d/]],x=/([\+\-]|\d\d)/gi,y="Month|Date|Hours|Minutes|Seconds|Milliseconds".split("|"),z={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},A={},B="DDD w M D d".split(" "),C="M D H h m s w".split(" "),D={M:function(){return this.month()+1},MMM:function(a){return E("monthsShort",this.month(),this,a)},MMMM:function(a){return E("months",this.month(),this,a)},D:function(){return this.date()},DDD:function(){var a=new Date(this.year(),this.month(),this.date()),b=new Date(this.year(),0,1);return~~((a-b)/864e5+1.5)},d:function(){return this.day()},dd:function(a){return E("weekdaysMin",this.day(),this,a)},ddd:function(a){return E("weekdaysShort",this.day(),this,a)},dddd:function(a){return E("weekdays",this.day(),this,a)},w:function(){var a=new Date(this.year(),this.month(),this.date()-this.day()+5),b=new Date(a.getFullYear(),0,4);return~~((a-b)/864e5/7+1.5)},YY:function(){return K(this.year()%100,2)},YYYY:function(){return K(this.year(),4)},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return~~(this.milliseconds()/100)},SS:function(){return K(~~(this.milliseconds()/10),2)},SSS:function(){return K(this.milliseconds(),3)},Z:function(){var a=-this.zone(),b="+";return a<0&&(a=-a,b="-"),b+K(~~(a/60),2)+":"+K(~~a%60,2)},ZZ:function(){var a=-this.zone(),b="+";return a<0&&(a=-a,b="-"),b+K(~~(10*a/6),4)}};while(B.length)e=B.pop(),D[e+"o"]=G(D[e]);while(C.length)e=C.pop(),D[e+e]=F(D[e],2);D.DDDD=F(D.DDD,3),b=function(c,d){if(c===null||c==="")return null;var e,f;return b.isMoment(c)?new H(new Date(+c._d),c._isUTC,c._lang):(d?M(d)?e=X(c,d):e=W(c,d):(f=j.exec(c),e=c===a?new Date:f?new Date(+f[1]):c instanceof Date?c:M(c)?O(c):typeof c=="string"?Y(c):new Date(c)),new H(e))},b.utc=function(a,c){return M(a)?new H(O(a,!0),!0):(typeof a=="string"&&!s.exec(a)&&(a+=" +0000",c&&(c+=" Z")),b(a,c).utc())},b.unix=function(a){return b(a*1e3)},b.duration=function(a,c){var d=b.isDuration(a),e=typeof a=="number",f=d?a._data:e?{}:a,g;return e&&(c?f[c]=a:f.milliseconds=a),g=new I(f),d&&(g._lang=a._lang),g},b.humanizeDuration=function(a,c,d){return b.duration(a,c===!0?null:c).humanize(c===!0?!0:d)},b.version=c,b.defaultFormat=v,b.lang=function(a,c){var d;if(!a)return g;(c||!f[a])&&P(a,c);if(f[a]){for(d=0;d11?c?"pm":"PM":c?"am":"AM"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10;return~~(a%100/10)===1?"th":b===1?"st":b===2?"nd":b===3?"rd":"th"}}),b.fn=H.prototype={clone:function(){return b(this)},valueOf:function(){return+this._d},unix:function(){return Math.floor(+this._d/1e3)},toString:function(){return this._d.toString()},toDate:function(){return this._d},toArray:function(){var a=this;return[a.year(),a.month(),a.date(),a.hours(),a.minutes(),a.seconds(),a.milliseconds(),!!this._isUTC]},isValid:function(){return this._a?this._a[8]!=null?!!this._a[8]:!N(this._a,(this._a[7]?b.utc(this._a):b(this._a)).toArray()):!isNaN(this._d.getTime())},utc:function(){return this._isUTC=!0,this},local:function(){return this._isUTC=!1,this},format:function(a){return T(this,a?a:b.defaultFormat)},add:function(a,c){var d=c?b.duration(+c,a):b.duration(a);return L(this,d,1),this},subtract:function(a,c){var d=c?b.duration(+c,a):b.duration(a);return L(this,d,-1),this},diff:function(a,c,e){var f=this._isUTC?b(a).utc():b(a).local(),g=(this.zone()-f.zone())*6e4,h=this._d-f._d-g,i=this.year()-f.year(),j=this.month()-f.month(),k=this.date()-f.date(),l;return c==="months"?l=i*12+j+k/30:c==="years"?l=i+(j+k/30)/12:l=c==="seconds"?h/1e3:c==="minutes"?h/6e4:c==="hours"?h/36e5:c==="days"?h/864e5:c==="weeks"?h/6048e5:h,e?l:d(l)},from:function(a,c){return b.duration(this.diff(a)).lang(this._lang).humanize(!c)},fromNow:function(a){return this.from(b(),a)},calendar:function(){var a=this.diff(b().sod(),"days",!0),c=this.lang().calendar,d=c.sameElse,e=a<-6?d:a<-1?c.lastWeek:a<0?c.lastDay:a<1?c.sameDay:a<2?c.nextDay:a<7?c.nextWeek:d;return this.format(typeof e=="function"?e.apply(this):e)},isLeapYear:function(){var a=this.year();return a%4===0&&a%100!==0||a%400===0},isDST:function(){return this.zone()= 0) return url;
46 | if (server.indexOf("://") < 0) server = "http://" + server;
47 | if (server.substr(-1) == "/") {
48 | server = server.substr(0, server.length - 1);
49 | }
50 | if (url.charAt(0) === "/") url = url.substr(1);
51 |
52 | return server + "/" + url;
53 | }
54 |
55 | function callES(server, url, method, data, successCallback, completeCallback) {
56 |
57 | url = constructESUrl(server, url);
58 | var uname_password_re = /^(https?:\/\/)?(?:(?:(.*):)?(.*?)@)?(.*)$/;
59 | var url_parts = url.match(uname_password_re);
60 |
61 | var uname = url_parts[2];
62 | var password = url_parts[3];
63 | url = url_parts[1] + url_parts[4];
64 | console.log("Calling " + url + " (uname: " + uname + " pwd: " + password + ")");
65 | if (data && method == "GET") method = "POST";
66 |
67 | $.ajax({
68 | url: url,
69 | data: method == "GET" ? null : data,
70 | // xhrFields: {
71 | // withCredentials: true
72 | // },
73 | // headers: {
74 | // "Authorization": "Basic " + btoa(uname + ":" + password)
75 | // },
76 | // beforeSend: function(xhr){
77 | // xhr.withCredentials = true;
78 | // xhr.setRequestHeader("Authorization", "Basic " + btoa(uname + ":" + password));
79 | // },
80 |
81 | password: password,
82 | username: uname,
83 | crossDomain: true,
84 | type: method,
85 | dataType: "json",
86 | complete: completeCallback,
87 | success: successCallback
88 | });
89 | }
90 |
91 | function submitCurrentRequestToES() {
92 | var req = sense.utils.getCurrentRequest();
93 | if (!req) return;
94 |
95 | $("#notification").text("Calling ES....").css("visibility", "visible");
96 | sense.output.getSession().setValue('');
97 |
98 | var es_server = $("#es_server").val(),
99 | es_url = req.url,
100 | es_method = req.method,
101 | es_data = req.data.join("\n");
102 | if (es_data) es_data += "\n"; //append a new line for bulk requests.
103 |
104 | callES(es_server, es_url, es_method, es_data, null, function (xhr, status) {
105 | $("#notification").text("").css("visibility", "hidden");
106 | if (typeof xhr.status == "number" &&
107 | ((xhr.status >= 400 && xhr.status < 600) ||
108 | (xhr.status >= 200 && xhr.status < 300)
109 | )) {
110 | // we have someone on the other side. Add to history
111 | sense.history.addToHistory(es_server, es_url, es_method, es_data);
112 |
113 |
114 | var value = xhr.responseText;
115 | try {
116 | value = JSON.stringify(JSON.parse(value), null, 3);
117 | }
118 | catch (e) {
119 |
120 | }
121 | sense.output.getSession().setValue(value);
122 | }
123 | else {
124 | sense.output.getSession().setValue("Request failed to get to the server (status code: " + xhr.status + "):" + xhr.responseText);
125 | }
126 |
127 | }
128 | );
129 |
130 | saveEditorState();
131 |
132 | _gaq.push(['_trackEvent', "elasticsearch", 'query']);
133 | }
134 |
135 | submitCurrentRequestToES = autoRetryIfTokenizing(submitCurrentRequestToES);
136 |
137 | function reformatData(data, indent) {
138 | var changed = false;
139 | var formatted_data = [];
140 | for (var i = 0; i < data.length; i++) {
141 | var cur_doc = data[i];
142 | try {
143 | var new_doc = JSON.stringify(JSON.parse(cur_doc), null, indent ? 3 : 0);
144 | changed = changed || new_doc != cur_doc;
145 | formatted_data.push(new_doc);
146 | }
147 | catch (e) {
148 | console.log(e);
149 | formatted_data.push(cur_doc);
150 | }
151 | }
152 |
153 | return { changed: changed, data: formatted_data}
154 | }
155 |
156 |
157 | function autoIndent() {
158 | var req_range = sense.utils.getCurrentRequestRange();
159 | if (!req_range) return;
160 | var parsed_req = sense.utils.getCurrentRequest();
161 | if (parsed_req.data && parsed_req.data.length > 0) {
162 | var indent = parsed_req.data.length == 1; // unindent multi docs by default
163 | var formatted_data = reformatData(parsed_req.data, indent);
164 | if (!formatted_data.changed) {
165 | // toggle.
166 | formatted_data = reformatData(parsed_req.data, !indent);
167 | }
168 | parsed_req.data = formatted_data.data;
169 |
170 | sense.utils.replaceCurrentRequest(parsed_req, req_range);
171 | }
172 | }
173 |
174 | autoIndent = autoRetryIfTokenizing(autoIndent);
175 |
176 | function copyToClipboard(value) {
177 | var currentActive = document.activeElement;
178 | var clipboardStaging = $("#clipboardStaging");
179 | clipboardStaging.val(value);
180 | clipboardStaging.select();
181 | document.execCommand("Copy", false);
182 | $(currentActive).focus(); // restore focus.
183 | }
184 |
185 | function copyAsCURL() {
186 | var req = sense.utils.getCurrentRequest();
187 | if (!req) return;
188 |
189 | _gaq.push(['_trackEvent', "curl", 'copied']);
190 |
191 | var es_server = $("#es_server").val(),
192 | es_url = req.url,
193 | es_method = req.method,
194 | es_data = req.data;
195 |
196 | var url = constructESUrl(es_server, es_url);
197 |
198 | var curl = 'curl -X' + es_method + ' "' + url + '"';
199 | if (es_data && es_data.length) {
200 | curl += " -d'\n";
201 | // since Sense doesn't allow single quote json string any single qoute is within a string.
202 | curl += es_data.join("\n").replace(/'/g, '\\"');
203 | if (es_data.length > 1) curl += "\n"; // end with a new line
204 | curl += "'";
205 | }
206 |
207 | //console.log(curl);
208 | copyToClipboard(curl);
209 |
210 | }
211 |
212 | copyAsCURL = autoRetryIfTokenizing(copyAsCURL, true);
213 |
214 |
215 | function handleCURLPaste(text) {
216 | _gaq.push(['_trackEvent', "curl", 'pasted']);
217 | var curlInput = sense.curl.parseCURL(text);
218 | if ($("#es_server").val()) curlInput.server = null; // do not override server
219 |
220 | if (!curlInput.method) curlInput.method = "GET";
221 |
222 | sense.editor.insert(sense.utils.textFromRequest(curlInput));
223 |
224 | }
225 |
226 |
227 | var CURRENT_REQ_RANGE = null;
228 |
229 |
230 | function saveEditorState() {
231 | try {
232 | var content = sense.editor.getValue();
233 | var server = $("#es_server").val();
234 | sense.history.saveCurrentEditorState(server, content);
235 | }
236 | catch (e) {
237 | console.log("Ignoring saving error: " + e)
238 | }
239 | }
240 |
241 | function updateEditorActionsBar() {
242 | var editor_actions = $("#editor_actions");
243 |
244 | if (CURRENT_REQ_RANGE) {
245 | var row = CURRENT_REQ_RANGE.start.row;
246 | var column = CURRENT_REQ_RANGE.start.column;
247 | var session = sense.editor.session;
248 | var firstLine = session.getLine(row);
249 | var offset = 0;
250 | if (firstLine.length > session.getScreenWidth() - 5) {
251 | // overlap first row
252 | if (row > 0) row--; else row++;
253 | }
254 | var screen_pos = sense.editor.renderer.textToScreenCoordinates(row, column);
255 | offset += screen_pos.pageY - 3;
256 | var end_offset = sense.editor.renderer.textToScreenCoordinates(CURRENT_REQ_RANGE.end.row,
257 | CURRENT_REQ_RANGE.end.column).pageY;
258 |
259 | offset = Math.min(end_offset, Math.max(offset, 47));
260 | if (offset >= 47) {
261 | editor_actions.css("top", Math.max(offset, 47));
262 | editor_actions.css('visibility', 'visible');
263 | }
264 | else {
265 | editor_actions.css("top", 0);
266 | editor_actions.css('visibility', 'hidden');
267 | }
268 | }
269 | else {
270 | editor_actions.css("top", 0);
271 | editor_actions.css('visibility', 'hidden');
272 | }
273 |
274 | }
275 |
276 | function highlighCurrentRequestAndUpdateActionBar() {
277 | var session = sense.editor.getSession();
278 | var new_current_req_range = sense.utils.getCurrentRequestRange();
279 | if (new_current_req_range == null && CURRENT_REQ_RANGE == null) return;
280 | if (new_current_req_range != null && CURRENT_REQ_RANGE != null &&
281 | new_current_req_range.start.row == CURRENT_REQ_RANGE.start.row &&
282 | new_current_req_range.end.row == CURRENT_REQ_RANGE.end.row
283 | ) {
284 | // same request, now see if we are on the first line and update the action bar
285 | var cursorRow = sense.editor.getCursorPosition().row;
286 | if (cursorRow == CURRENT_REQ_RANGE.start.row) {
287 | updateEditorActionsBar();
288 | }
289 | return; // nothing to do..
290 | }
291 |
292 | if (CURRENT_REQ_RANGE) {
293 | session.removeMarker(CURRENT_REQ_RANGE.marker_id);
294 | }
295 |
296 | CURRENT_REQ_RANGE = new_current_req_range;
297 | if (CURRENT_REQ_RANGE) {
298 | CURRENT_REQ_RANGE.marker_id = session.addMarker(CURRENT_REQ_RANGE, "ace_snippet-marker", "text");
299 | }
300 | updateEditorActionsBar();
301 | }
302 |
303 | highlighCurrentRequestAndUpdateActionBar = autoRetryIfTokenizing(highlighCurrentRequestAndUpdateActionBar, true);
304 |
305 | function moveToPreviousRequestEdge() {
306 | var pos = sense.editor.getCursorPosition();
307 | for (pos.row--; pos.row > 0 && !sense.utils.isRequestEdge(pos.row); pos.row--) {
308 | }
309 | sense.editor.moveCursorTo(pos.row, 0);
310 | }
311 |
312 | moveToPreviousRequestEdge = autoRetryIfTokenizing(moveToPreviousRequestEdge);
313 |
314 |
315 | function moveToNextRequestEdge() {
316 | var pos = sense.editor.getCursorPosition();
317 | var maxRow = sense.editor.getSession().getLength();
318 | for (pos.row++; pos.row < maxRow && !sense.utils.isRequestEdge(pos.row); pos.row++) {
319 | }
320 | sense.editor.moveCursorTo(pos.row, 0);
321 | }
322 |
323 | moveToNextRequestEdge = autoRetryIfTokenizing(moveToNextRequestEdge);
324 |
325 | function init() {
326 |
327 | sense.editor = ace.edit("editor");
328 | ace.require("ace/mode/sense");
329 | sense.editor.getSession().setMode("ace/mode/sense");
330 | sense.editor.setShowPrintMargin(false);
331 | sense.editor.getSession().setFoldStyle('markbeginend');
332 | sense.editor.getSession().setUseWrapMode(true);
333 | sense.editor.commands.addCommand({
334 | name: 'autocomplete',
335 | bindKey: {win: 'Ctrl-Space', mac: 'Ctrl-Space'},
336 | exec: sense.autocomplete.editorAutocompleteCommand
337 | });
338 | sense.editor.commands.addCommand({
339 | name: 'auto indent request',
340 | bindKey: {win: 'Ctrl-I', mac: 'Command-I'},
341 | exec: autoIndent
342 | });
343 | sense.editor.commands.addCommand({
344 | name: 'send to elasticsearch',
345 | bindKey: {win: 'Ctrl-Enter', mac: 'Command-Enter'},
346 | exec: submitCurrentRequestToES
347 | });
348 |
349 | sense.editor.commands.addCommand({
350 | name: 'copy as cUrl',
351 | bindKey: {win: 'Ctrl-Shift-C', mac: 'Command-Shift-C'},
352 | exec: copyAsCURL
353 | });
354 |
355 | sense.editor.commands.addCommand({
356 | name: 'move to previous request start or end',
357 | bindKey: {win: 'Ctrl-Up', mac: 'Command-Up'},
358 | exec: moveToPreviousRequestEdge
359 | });
360 |
361 | sense.editor.commands.addCommand({
362 | name: 'move to next request start or end',
363 | bindKey: {win: 'Ctrl-Down', mac: 'Command-Down'},
364 | exec: moveToNextRequestEdge
365 | });
366 |
367 |
368 | var orig_paste = sense.editor.onPaste;
369 | sense.editor.onPaste = function (text) {
370 | if (text && sense.curl.detectCURL(text)) {
371 | handleCURLPaste(text);
372 | return;
373 | }
374 | orig_paste.call(this, text);
375 | };
376 |
377 | sense.editor.getSession().on('tokenizerUpdate', function (e) {
378 | highlighCurrentRequestAndUpdateActionBar();
379 | });
380 |
381 | sense.editor.getSession().selection.on('changeCursor', function (e) {
382 | highlighCurrentRequestAndUpdateActionBar();
383 | });
384 |
385 |
386 | var save_generation = 0;
387 |
388 | function get_save_callback(for_generation) {
389 | return function () {
390 | if (save_generation == for_generation) {
391 | saveEditorState();
392 | }
393 | }
394 | }
395 |
396 | sense.editor.getSession().on("change", function (e) {
397 | setTimeout(get_save_callback(++save_generation), 500);
398 | });
399 |
400 | sense.editor.getSession().on("changeScrollTop", updateEditorActionsBar);
401 |
402 |
403 | sense.output = ace.edit("output");
404 | sense.output.getSession().setMode("ace/mode/json");
405 | sense.output.getSession().setFoldStyle('markbeginend');
406 | sense.output.setTheme("ace/theme/monokai");
407 | sense.output.getSession().setUseWrapMode(true);
408 | sense.output.setShowPrintMargin(false);
409 | sense.output.setReadOnly(true);
410 |
411 | var editorElement = $("#editor"),
412 | outputElement = $("#output"),
413 | editorActions = $("#editor_actions");
414 |
415 |
416 | editorElement.resizable(
417 | {
418 | autoHide: false,
419 | handles: 'e',
420 | start: function (e, ui) {
421 | editor_resizebar = $(".ui-resizable-e").addClass("active");
422 | },
423 | stop: function (e, ui) {
424 | editor_resizebar = $(".ui-resizable-e").removeClass("active");
425 |
426 | var parent = ui.element.parent();
427 | var editorSize = ui.element.outerWidth();
428 | outputElement.css("left", editorSize);
429 | editorActions.css("margin-right", -editorSize + 3);
430 | sense.editor.resize(true);
431 | sense.output.resize(true);
432 | }
433 | });
434 |
435 | sense.history.init();
436 | sense.autocomplete.init();
437 |
438 | $("#send").tooltip();
439 | $("#send").click(function () {
440 | submitCurrentRequestToES();
441 | return false;
442 | });
443 |
444 | $("#copy_as_curl").click(function (e) {
445 | copyAsCURL();
446 | e.preventDefault();
447 | });
448 |
449 | $("#auto_indent").click(function (e) {
450 | autoIndent();
451 | e.preventDefault();
452 | });
453 |
454 | var help_popup = $("#help_popup");
455 |
456 | help_popup.on('shown', function () {
457 | _gaq.push(['_trackEvent', "help", 'shown']);
458 | $(' PUT index/type/1\n'
459 | + '{\n'
460 | + ' "body": "here"\n'
461 | + '}\n\n'
462 | + 'GET index/type/1\n'
463 | + '
').appendTo(help_popup.find("#example_editor_container"));
464 |
465 | var example_editor = ace.edit("example_editor");
466 | example_editor.getSession().setMode("ace/mode/sense");
467 | example_editor.getSession().setFoldStyle('markbeginend');
468 | example_editor.setReadOnly(true);
469 | example_editor.renderer.setShowPrintMargin(false);
470 | });
471 |
472 | help_popup.on('hidden', function () {
473 | help_popup.find('#example_editor').remove();
474 |
475 | });
476 |
477 |
478 | var es_server = $("#es_server");
479 |
480 | es_server.blur(function () {
481 | sense.mappings.notifyServerChange(es_server.val());
482 | });
483 |
484 | var editor_source = sense.utils.getUrlParam('load_from') || "stored";
485 | var last_editor_state = sense.history.getSavedEditorState();
486 | if (editor_source == "stored") {
487 | if (last_editor_state) {
488 | resetToValues(last_editor_state.server, last_editor_state.content);
489 | }
490 | else {
491 | autoIndent();
492 | }
493 | }
494 | else if (/^https?:\/\//.exec(editor_source)) {
495 | $.get(editor_source, null, function (data) {
496 | resetToValues(null, data);
497 | highlighCurrentRequestAndUpdateActionBar();
498 | updateEditorActionsBar();
499 | });
500 | }
501 | else {
502 | if (last_editor_state) {
503 | resetToValues(last_editor_state.server);
504 | }
505 | }
506 |
507 | if (document.location.pathname && document.location.pathname.indexOf("_plugin") == 1) {
508 | // running as an ES plugin. Always assume we are using that elasticsearch
509 | resetToValues(document.location.host);
510 | }
511 |
512 | sense.editor.focus();
513 | highlighCurrentRequestAndUpdateActionBar();
514 | updateEditorActionsBar();
515 |
516 | if (!localStorage.getItem("version_welcome_shown")) {
517 | localStorage.setItem("version_welcome_shown", sense.VERSION);
518 | var welcome_popup = $("#welcome_popup");
519 | welcome_popup.modal();
520 | welcome_popup.on('shown', function () {
521 | $('PUT index/type/1\n'
522 | + '{\n'
523 | + ' "body": "here"\n'
524 | + '}\n\n'
525 | + 'GET index/type/1\n'
526 | + '
').appendTo(welcome_popup.find("#example_editor_container"));
527 |
528 | var example_editor = ace.edit("example_editor");
529 | example_editor.getSession().setMode("ace/mode/sense");
530 | example_editor.getSession().setFoldStyle('markbeginend');
531 | example_editor.setReadOnly(true);
532 | example_editor.renderer.setShowPrintMargin(false);
533 | });
534 |
535 | welcome_popup.on('hidden', function () {
536 | welcome_popup.find('#example_editor').remove();
537 |
538 | });
539 | // welcome_popup.modal('show');
540 |
541 | }
542 | }
543 |
544 | $(document).ready(init);
545 |
546 | /* google analytics */
547 | var _gaq = _gaq || [];
548 | _gaq.push(['_setAccount', 'UA-11830182-16']);
549 | _gaq.push(['_setCustomVar',
550 | 1, // This custom var is set to slot #1. Required parameter.
551 | 'Version', // The name of the custom variable. Required parameter.
552 | sense.VERSION, // The value of the custom variable. Required parameter.
553 | 1 // Sets the scope to visitor-level. Optional parameter.
554 | ]);
555 |
556 | _gaq.push(['_trackPageview']);
557 |
558 | (function () {
559 | var ga = document.createElement('script');
560 | ga.type = 'text/javascript';
561 | ga.async = true;
562 | ga.src = 'https://ssl.google-analytics.com/ga.js';
563 | var s = document.getElementsByTagName('script')[0];
564 | s.parentNode.insertBefore(ga, s);
565 | })();
566 |
567 |
--------------------------------------------------------------------------------
/lib/src-noconflict/mode-json.js:
--------------------------------------------------------------------------------
1 | /* ***** BEGIN LICENSE BLOCK *****
2 | * Distributed under the BSD license:
3 | *
4 | * Copyright (c) 2010, Ajax.org B.V.
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without
8 | * modification, are permitted provided that the following conditions are met:
9 | * * Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * * Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * * Neither the name of Ajax.org B.V. nor the
15 | * names of its contributors may be used to endorse or promote products
16 | * derived from this software without specific prior written permission.
17 | *
18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
22 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 | *
29 | * ***** END LICENSE BLOCK ***** */
30 |
31 | ace.define('ace/mode/json', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text', 'ace/tokenizer', 'ace/mode/json_highlight_rules', 'ace/mode/matching_brace_outdent', 'ace/mode/behaviour/cstyle', 'ace/mode/folding/cstyle', 'ace/worker/worker_client'], function(require, exports, module) {
32 |
33 |
34 | var oop = require("../lib/oop");
35 | var TextMode = require("./text").Mode;
36 | var Tokenizer = require("../tokenizer").Tokenizer;
37 | var HighlightRules = require("./json_highlight_rules").JsonHighlightRules;
38 | var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
39 | var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
40 | var CStyleFoldMode = require("./folding/cstyle").FoldMode;
41 | var WorkerClient = require("../worker/worker_client").WorkerClient;
42 |
43 | var Mode = function() {
44 | this.$tokenizer = new Tokenizer(new HighlightRules().getRules());
45 | this.$outdent = new MatchingBraceOutdent();
46 | this.$behaviour = new CstyleBehaviour();
47 | this.foldingRules = new CStyleFoldMode();
48 | };
49 | oop.inherits(Mode, TextMode);
50 |
51 | (function() {
52 |
53 | this.getNextLineIndent = function(state, line, tab) {
54 | var indent = this.$getIndent(line);
55 |
56 | if (state == "start") {
57 | var match = line.match(/^.*[\{\(\[]\s*$/);
58 | if (match) {
59 | indent += tab;
60 | }
61 | }
62 |
63 | return indent;
64 | };
65 |
66 | this.checkOutdent = function(state, line, input) {
67 | return this.$outdent.checkOutdent(line, input);
68 | };
69 |
70 | this.autoOutdent = function(state, doc, row) {
71 | this.$outdent.autoOutdent(doc, row);
72 | };
73 |
74 | this.createWorker = function(session) {
75 | var worker = new WorkerClient(["ace"], "ace/mode/json_worker", "JsonWorker");
76 | worker.attachToDocument(session.getDocument());
77 |
78 | worker.on("error", function(e) {
79 | session.setAnnotations([e.data]);
80 | });
81 |
82 | worker.on("ok", function() {
83 | session.clearAnnotations();
84 | });
85 |
86 | return worker;
87 | };
88 |
89 |
90 | }).call(Mode.prototype);
91 |
92 | exports.Mode = Mode;
93 | });
94 |
95 | ace.define('ace/mode/json_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text_highlight_rules'], function(require, exports, module) {
96 |
97 |
98 | var oop = require("../lib/oop");
99 | var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
100 |
101 | var JsonHighlightRules = function() {
102 | this.$rules = {
103 | "start" : [
104 | {
105 | token : "variable", // single line
106 | regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)'
107 | }, {
108 | token : "string", // single line
109 | regex : '"',
110 | next : "string"
111 | }, {
112 | token : "constant.numeric", // hex
113 | regex : "0[xX][0-9a-fA-F]+\\b"
114 | }, {
115 | token : "constant.numeric", // float
116 | regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
117 | }, {
118 | token : "constant.language.boolean",
119 | regex : "(?:true|false)\\b"
120 | }, {
121 | token : "invalid.illegal", // single quoted strings are not allowed
122 | regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
123 | }, {
124 | token : "invalid.illegal", // comments are not allowed
125 | regex : "\\/\\/.*$"
126 | }, {
127 | token : "paren.lparen",
128 | regex : "[[({]"
129 | }, {
130 | token : "paren.rparen",
131 | regex : "[\\])}]"
132 | }, {
133 | token : "text",
134 | regex : "\\s+"
135 | }
136 | ],
137 | "string" : [
138 | {
139 | token : "constant.language.escape",
140 | regex : /\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|["\\\/bfnrt])/
141 | }, {
142 | token : "string",
143 | regex : '[^"\\\\]+',
144 | merge : true
145 | }, {
146 | token : "string",
147 | regex : '"',
148 | next : "start",
149 | merge : true
150 | }, {
151 | token : "string",
152 | regex : "",
153 | next : "start",
154 | merge : true
155 | }
156 | ]
157 | };
158 |
159 | };
160 |
161 | oop.inherits(JsonHighlightRules, TextHighlightRules);
162 |
163 | exports.JsonHighlightRules = JsonHighlightRules;
164 | });
165 |
166 | ace.define('ace/mode/matching_brace_outdent', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) {
167 |
168 |
169 | var Range = require("../range").Range;
170 |
171 | var MatchingBraceOutdent = function() {};
172 |
173 | (function() {
174 |
175 | this.checkOutdent = function(line, input) {
176 | if (! /^\s+$/.test(line))
177 | return false;
178 |
179 | return /^\s*\}/.test(input);
180 | };
181 |
182 | this.autoOutdent = function(doc, row) {
183 | var line = doc.getLine(row);
184 | var match = line.match(/^(\s*\})/);
185 |
186 | if (!match) return 0;
187 |
188 | var column = match[1].length;
189 | var openBracePos = doc.findMatchingBracket({row: row, column: column});
190 |
191 | if (!openBracePos || openBracePos.row == row) return 0;
192 |
193 | var indent = this.$getIndent(doc.getLine(openBracePos.row));
194 | doc.replace(new Range(row, 0, row, column-1), indent);
195 | };
196 |
197 | this.$getIndent = function(line) {
198 | var match = line.match(/^(\s+)/);
199 | if (match) {
200 | return match[1];
201 | }
202 |
203 | return "";
204 | };
205 |
206 | }).call(MatchingBraceOutdent.prototype);
207 |
208 | exports.MatchingBraceOutdent = MatchingBraceOutdent;
209 | });
210 |
211 | ace.define('ace/mode/behaviour/cstyle', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/behaviour', 'ace/token_iterator'], function(require, exports, module) {
212 |
213 |
214 | var oop = require("../../lib/oop");
215 | var Behaviour = require("../behaviour").Behaviour;
216 | var TokenIterator = require("../../token_iterator").TokenIterator;
217 |
218 | var autoInsertedBrackets = 0;
219 | var autoInsertedRow = -1;
220 | var autoInsertedLineEnd = "";
221 |
222 | var CstyleBehaviour = function () {
223 |
224 | CstyleBehaviour.isSaneInsertion = function(editor, session) {
225 | var cursor = editor.getCursorPosition();
226 | var iterator = new TokenIterator(session, cursor.row, cursor.column);
227 | if (!this.$matchTokenType(iterator.getCurrentToken() || "text", ["text", "paren.rparen"])) {
228 | iterator = new TokenIterator(session, cursor.row, cursor.column + 1);
229 | if (!this.$matchTokenType(iterator.getCurrentToken() || "text", ["text", "paren.rparen"]))
230 | return false;
231 | }
232 | iterator.stepForward();
233 | return iterator.getCurrentTokenRow() !== cursor.row ||
234 | this.$matchTokenType(iterator.getCurrentToken() || "text", ["text", "comment", "paren.rparen"]);
235 | };
236 |
237 | CstyleBehaviour.$matchTokenType = function(token, types) {
238 | return types.indexOf(token.type || token) > -1;
239 | };
240 |
241 | CstyleBehaviour.recordAutoInsert = function(editor, session, bracket) {
242 | var cursor = editor.getCursorPosition();
243 | var line = session.doc.getLine(cursor.row);
244 | if (!this.isAutoInsertedClosing(cursor, line, autoInsertedLineEnd[0]))
245 | autoInsertedBrackets = 0;
246 | autoInsertedRow = cursor.row;
247 | autoInsertedLineEnd = bracket + line.substr(cursor.column);
248 | autoInsertedBrackets++;
249 | };
250 |
251 | CstyleBehaviour.isAutoInsertedClosing = function(cursor, line, bracket) {
252 | return autoInsertedBrackets > 0 &&
253 | cursor.row === autoInsertedRow &&
254 | bracket === autoInsertedLineEnd[0] &&
255 | line.substr(cursor.column) === autoInsertedLineEnd;
256 | };
257 |
258 | CstyleBehaviour.popAutoInsertedClosing = function() {
259 | autoInsertedLineEnd = autoInsertedLineEnd.substr(1);
260 | autoInsertedBrackets--;
261 | };
262 |
263 | this.add("braces", "insertion", function (state, action, editor, session, text) {
264 | if (text == '{') {
265 | var selection = editor.getSelectionRange();
266 | var selected = session.doc.getTextRange(selection);
267 | if (selected !== "" && selected !== "{") {
268 | return {
269 | text: '{' + selected + '}',
270 | selection: false
271 | };
272 | } else if (CstyleBehaviour.isSaneInsertion(editor, session)) {
273 | CstyleBehaviour.recordAutoInsert(editor, session, "}");
274 | return {
275 | text: '{}',
276 | selection: [1, 1]
277 | };
278 | }
279 | } else if (text == '}') {
280 | var cursor = editor.getCursorPosition();
281 | var line = session.doc.getLine(cursor.row);
282 | var rightChar = line.substring(cursor.column, cursor.column + 1);
283 | if (rightChar == '}') {
284 | var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row});
285 | if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) {
286 | CstyleBehaviour.popAutoInsertedClosing();
287 | return {
288 | text: '',
289 | selection: [1, 1]
290 | };
291 | }
292 | }
293 | } else if (text == "\n" || text == "\r\n") {
294 | var cursor = editor.getCursorPosition();
295 | var line = session.doc.getLine(cursor.row);
296 | var rightChar = line.substring(cursor.column, cursor.column + 1);
297 | if (rightChar == '}') {
298 | var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column + 1});
299 | if (!openBracePos)
300 | return null;
301 |
302 | var indent = this.getNextLineIndent(state, line.substring(0, line.length - 1), session.getTabString());
303 | var next_indent = this.$getIndent(session.doc.getLine(openBracePos.row));
304 |
305 | return {
306 | text: '\n' + indent + '\n' + next_indent,
307 | selection: [1, indent.length, 1, indent.length]
308 | };
309 | }
310 | }
311 | });
312 |
313 | this.add("braces", "deletion", function (state, action, editor, session, range) {
314 | var selected = session.doc.getTextRange(range);
315 | if (!range.isMultiLine() && selected == '{') {
316 | var line = session.doc.getLine(range.start.row);
317 | var rightChar = line.substring(range.end.column, range.end.column + 1);
318 | if (rightChar == '}') {
319 | range.end.column++;
320 | return range;
321 | }
322 | }
323 | });
324 |
325 | this.add("parens", "insertion", function (state, action, editor, session, text) {
326 | if (text == '(') {
327 | var selection = editor.getSelectionRange();
328 | var selected = session.doc.getTextRange(selection);
329 | if (selected !== "") {
330 | return {
331 | text: '(' + selected + ')',
332 | selection: false
333 | };
334 | } else if (CstyleBehaviour.isSaneInsertion(editor, session)) {
335 | CstyleBehaviour.recordAutoInsert(editor, session, ")");
336 | return {
337 | text: '()',
338 | selection: [1, 1]
339 | };
340 | }
341 | } else if (text == ')') {
342 | var cursor = editor.getCursorPosition();
343 | var line = session.doc.getLine(cursor.row);
344 | var rightChar = line.substring(cursor.column, cursor.column + 1);
345 | if (rightChar == ')') {
346 | var matching = session.$findOpeningBracket(')', {column: cursor.column + 1, row: cursor.row});
347 | if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) {
348 | CstyleBehaviour.popAutoInsertedClosing();
349 | return {
350 | text: '',
351 | selection: [1, 1]
352 | };
353 | }
354 | }
355 | }
356 | });
357 |
358 | this.add("parens", "deletion", function (state, action, editor, session, range) {
359 | var selected = session.doc.getTextRange(range);
360 | if (!range.isMultiLine() && selected == '(') {
361 | var line = session.doc.getLine(range.start.row);
362 | var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
363 | if (rightChar == ')') {
364 | range.end.column++;
365 | return range;
366 | }
367 | }
368 | });
369 |
370 | this.add("brackets", "insertion", function (state, action, editor, session, text) {
371 | if (text == '[') {
372 | var selection = editor.getSelectionRange();
373 | var selected = session.doc.getTextRange(selection);
374 | if (selected !== "") {
375 | return {
376 | text: '[' + selected + ']',
377 | selection: false
378 | };
379 | } else if (CstyleBehaviour.isSaneInsertion(editor, session)) {
380 | CstyleBehaviour.recordAutoInsert(editor, session, "]");
381 | return {
382 | text: '[]',
383 | selection: [1, 1]
384 | };
385 | }
386 | } else if (text == ']') {
387 | var cursor = editor.getCursorPosition();
388 | var line = session.doc.getLine(cursor.row);
389 | var rightChar = line.substring(cursor.column, cursor.column + 1);
390 | if (rightChar == ']') {
391 | var matching = session.$findOpeningBracket(']', {column: cursor.column + 1, row: cursor.row});
392 | if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) {
393 | CstyleBehaviour.popAutoInsertedClosing();
394 | return {
395 | text: '',
396 | selection: [1, 1]
397 | };
398 | }
399 | }
400 | }
401 | });
402 |
403 | this.add("brackets", "deletion", function (state, action, editor, session, range) {
404 | var selected = session.doc.getTextRange(range);
405 | if (!range.isMultiLine() && selected == '[') {
406 | var line = session.doc.getLine(range.start.row);
407 | var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
408 | if (rightChar == ']') {
409 | range.end.column++;
410 | return range;
411 | }
412 | }
413 | });
414 |
415 | this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
416 | if (text == '"' || text == "'") {
417 | var quote = text;
418 | var selection = editor.getSelectionRange();
419 | var selected = session.doc.getTextRange(selection);
420 | if (selected !== "") {
421 | return {
422 | text: quote + selected + quote,
423 | selection: false
424 | };
425 | } else {
426 | var cursor = editor.getCursorPosition();
427 | var line = session.doc.getLine(cursor.row);
428 | var leftChar = line.substring(cursor.column-1, cursor.column);
429 | if (leftChar == '\\') {
430 | return null;
431 | }
432 | var tokens = session.getTokens(selection.start.row);
433 | var col = 0, token;
434 | var quotepos = -1; // Track whether we're inside an open quote.
435 |
436 | for (var x = 0; x < tokens.length; x++) {
437 | token = tokens[x];
438 | if (token.type == "string") {
439 | quotepos = -1;
440 | } else if (quotepos < 0) {
441 | quotepos = token.value.indexOf(quote);
442 | }
443 | if ((token.value.length + col) > selection.start.column) {
444 | break;
445 | }
446 | col += tokens[x].value.length;
447 | }
448 | if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) {
449 | return {
450 | text: quote + quote,
451 | selection: [1,1]
452 | };
453 | } else if (token && token.type === "string") {
454 | var rightChar = line.substring(cursor.column, cursor.column + 1);
455 | if (rightChar == quote) {
456 | return {
457 | text: '',
458 | selection: [1, 1]
459 | };
460 | }
461 | }
462 | }
463 | }
464 | });
465 |
466 | this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
467 | var selected = session.doc.getTextRange(range);
468 | if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
469 | var line = session.doc.getLine(range.start.row);
470 | var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
471 | if (rightChar == '"') {
472 | range.end.column++;
473 | return range;
474 | }
475 | }
476 | });
477 |
478 | };
479 |
480 | oop.inherits(CstyleBehaviour, Behaviour);
481 |
482 | exports.CstyleBehaviour = CstyleBehaviour;
483 | });
484 |
485 | ace.define('ace/mode/folding/cstyle', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/range', 'ace/mode/folding/fold_mode'], function(require, exports, module) {
486 |
487 |
488 | var oop = require("../../lib/oop");
489 | var Range = require("../../range").Range;
490 | var BaseFoldMode = require("./fold_mode").FoldMode;
491 |
492 | var FoldMode = exports.FoldMode = function() {};
493 | oop.inherits(FoldMode, BaseFoldMode);
494 |
495 | (function() {
496 |
497 | this.foldingStartMarker = /(\{|\[)[^\}\]]*$|^\s*(\/\*)/;
498 | this.foldingStopMarker = /^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/;
499 |
500 | this.getFoldWidgetRange = function(session, foldStyle, row) {
501 | var line = session.getLine(row);
502 | var match = line.match(this.foldingStartMarker);
503 | if (match) {
504 | var i = match.index;
505 |
506 | if (match[1])
507 | return this.openingBracketBlock(session, match[1], row, i);
508 |
509 | return session.getCommentFoldRange(row, i + match[0].length, 1);
510 | }
511 |
512 | if (foldStyle !== "markbeginend")
513 | return;
514 |
515 | var match = line.match(this.foldingStopMarker);
516 | if (match) {
517 | var i = match.index + match[0].length;
518 |
519 | if (match[1])
520 | return this.closingBracketBlock(session, match[1], row, i);
521 |
522 | return session.getCommentFoldRange(row, i, -1);
523 | }
524 | };
525 |
526 | }).call(FoldMode.prototype);
527 |
528 | });
529 |
--------------------------------------------------------------------------------
/lib/bootstrap/js/bootstrap.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap.js by @fat & @mdo
3 | * Copyright 2012 Twitter, Inc.
4 | * http://www.apache.org/licenses/LICENSE-2.0.txt
5 | */
6 | !function(e){"use strict";e(function(){e.support.transition=function(){var e=function(){var e=document.createElement("bootstrap"),t={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},n;for(n in t)if(e.style[n]!==undefined)return t[n]}();return e&&{end:e}}()})}(window.jQuery),!function(e){"use strict";var t='[data-dismiss="alert"]',n=function(n){e(n).on("click",t,this.close)};n.prototype.close=function(t){function s(){i.trigger("closed").remove()}var n=e(this),r=n.attr("data-target"),i;r||(r=n.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,"")),i=e(r),t&&t.preventDefault(),i.length||(i=n.hasClass("alert")?n:n.parent()),i.trigger(t=e.Event("close"));if(t.isDefaultPrevented())return;i.removeClass("in"),e.support.transition&&i.hasClass("fade")?i.on(e.support.transition.end,s):s()},e.fn.alert=function(t){return this.each(function(){var r=e(this),i=r.data("alert");i||r.data("alert",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.alert.Constructor=n,e(document).on("click.alert.data-api",t,n.prototype.close)}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.button.defaults,n)};t.prototype.setState=function(e){var t="disabled",n=this.$element,r=n.data(),i=n.is("input")?"val":"html";e+="Text",r.resetText||n.data("resetText",n[i]()),n[i](r[e]||this.options[e]),setTimeout(function(){e=="loadingText"?n.addClass(t).attr(t,t):n.removeClass(t).removeAttr(t)},0)},t.prototype.toggle=function(){var e=this.$element.closest('[data-toggle="buttons-radio"]');e&&e.find(".active").removeClass("active"),this.$element.toggleClass("active")},e.fn.button=function(n){return this.each(function(){var r=e(this),i=r.data("button"),s=typeof n=="object"&&n;i||r.data("button",i=new t(this,s)),n=="toggle"?i.toggle():n&&i.setState(n)})},e.fn.button.defaults={loadingText:"loading..."},e.fn.button.Constructor=t,e(document).on("click.button.data-api","[data-toggle^=button]",function(t){var n=e(t.target);n.hasClass("btn")||(n=n.closest(".btn")),n.button("toggle")})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=n,this.options.slide&&this.slide(this.options.slide),this.options.pause=="hover"&&this.$element.on("mouseenter",e.proxy(this.pause,this)).on("mouseleave",e.proxy(this.cycle,this))};t.prototype={cycle:function(t){return t||(this.paused=!1),this.options.interval&&!this.paused&&(this.interval=setInterval(e.proxy(this.next,this),this.options.interval)),this},to:function(t){var n=this.$element.find(".item.active"),r=n.parent().children(),i=r.index(n),s=this;if(t>r.length-1||t<0)return;return this.sliding?this.$element.one("slid",function(){s.to(t)}):i==t?this.pause().cycle():this.slide(t>i?"next":"prev",e(r[t]))},pause:function(t){return t||(this.paused=!0),this.$element.find(".next, .prev").length&&e.support.transition.end&&(this.$element.trigger(e.support.transition.end),this.cycle()),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(t,n){var r=this.$element.find(".item.active"),i=n||r[t](),s=this.interval,o=t=="next"?"left":"right",u=t=="next"?"first":"last",a=this,f;this.sliding=!0,s&&this.pause(),i=i.length?i:this.$element.find(".item")[u](),f=e.Event("slide",{relatedTarget:i[0]});if(i.hasClass("active"))return;if(e.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(f);if(f.isDefaultPrevented())return;i.addClass(t),i[0].offsetWidth,r.addClass(o),i.addClass(o),this.$element.one(e.support.transition.end,function(){i.removeClass([t,o].join(" ")).addClass("active"),r.removeClass(["active",o].join(" ")),a.sliding=!1,setTimeout(function(){a.$element.trigger("slid")},0)})}else{this.$element.trigger(f);if(f.isDefaultPrevented())return;r.removeClass("active"),i.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return s&&this.cycle(),this}},e.fn.carousel=function(n){return this.each(function(){var r=e(this),i=r.data("carousel"),s=e.extend({},e.fn.carousel.defaults,typeof n=="object"&&n),o=typeof n=="string"?n:s.slide;i||r.data("carousel",i=new t(this,s)),typeof n=="number"?i.to(n):o?i[o]():s.interval&&i.cycle()})},e.fn.carousel.defaults={interval:5e3,pause:"hover"},e.fn.carousel.Constructor=t,e(document).on("click.carousel.data-api","[data-slide]",function(t){var n=e(this),r,i=e(n.attr("data-target")||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,"")),s=e.extend({},i.data(),n.data());i.carousel(s),t.preventDefault()})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.collapse.defaults,n),this.options.parent&&(this.$parent=e(this.options.parent)),this.options.toggle&&this.toggle()};t.prototype={constructor:t,dimension:function(){var e=this.$element.hasClass("width");return e?"width":"height"},show:function(){var t,n,r,i;if(this.transitioning)return;t=this.dimension(),n=e.camelCase(["scroll",t].join("-")),r=this.$parent&&this.$parent.find("> .accordion-group > .in");if(r&&r.length){i=r.data("collapse");if(i&&i.transitioning)return;r.collapse("hide"),i||r.data("collapse",null)}this.$element[t](0),this.transition("addClass",e.Event("show"),"shown"),e.support.transition&&this.$element[t](this.$element[0][n])},hide:function(){var t;if(this.transitioning)return;t=this.dimension(),this.reset(this.$element[t]()),this.transition("removeClass",e.Event("hide"),"hidden"),this.$element[t](0)},reset:function(e){var t=this.dimension();return this.$element.removeClass("collapse")[t](e||"auto")[0].offsetWidth,this.$element[e!==null?"addClass":"removeClass"]("collapse"),this},transition:function(t,n,r){var i=this,s=function(){n.type=="show"&&i.reset(),i.transitioning=0,i.$element.trigger(r)};this.$element.trigger(n);if(n.isDefaultPrevented())return;this.transitioning=1,this.$element[t]("in"),e.support.transition&&this.$element.hasClass("collapse")?this.$element.one(e.support.transition.end,s):s()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}},e.fn.collapse=function(n){return this.each(function(){var r=e(this),i=r.data("collapse"),s=typeof n=="object"&&n;i||r.data("collapse",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.collapse.defaults={toggle:!0},e.fn.collapse.Constructor=t,e(document).on("click.collapse.data-api","[data-toggle=collapse]",function(t){var n=e(this),r,i=n.attr("data-target")||t.preventDefault()||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,""),s=e(i).data("collapse")?"toggle":n.data();n[e(i).hasClass("in")?"addClass":"removeClass"]("collapsed"),e(i).collapse(s)})}(window.jQuery),!function(e){"use strict";function r(){e(t).each(function(){i(e(this)).removeClass("open")})}function i(t){var n=t.attr("data-target"),r;return n||(n=t.attr("href"),n=n&&/#/.test(n)&&n.replace(/.*(?=#[^\s]*$)/,"")),r=e(n),r.length||(r=t.parent()),r}var t="[data-toggle=dropdown]",n=function(t){var n=e(t).on("click.dropdown.data-api",this.toggle);e("html").on("click.dropdown.data-api",function(){n.parent().removeClass("open")})};n.prototype={constructor:n,toggle:function(t){var n=e(this),s,o;if(n.is(".disabled, :disabled"))return;return s=i(n),o=s.hasClass("open"),r(),o||(s.toggleClass("open"),n.focus()),!1},keydown:function(t){var n,r,s,o,u,a;if(!/(38|40|27)/.test(t.keyCode))return;n=e(this),t.preventDefault(),t.stopPropagation();if(n.is(".disabled, :disabled"))return;o=i(n),u=o.hasClass("open");if(!u||u&&t.keyCode==27)return n.click();r=e("[role=menu] li:not(.divider) a",o);if(!r.length)return;a=r.index(r.filter(":focus")),t.keyCode==38&&a>0&&a--,t.keyCode==40&&a ').appendTo(document.body),this.$backdrop.click(this.options.backdrop=="static"?e.proxy(this.$element[0].focus,this.$element[0]):e.proxy(this.hide,this)),i&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),i?this.$backdrop.one(e.support.transition.end,t):t()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),e.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(e.support.transition.end,e.proxy(this.removeBackdrop,this)):this.removeBackdrop()):t&&t()}},e.fn.modal=function(n){return this.each(function(){var r=e(this),i=r.data("modal"),s=e.extend({},e.fn.modal.defaults,r.data(),typeof n=="object"&&n);i||r.data("modal",i=new t(this,s)),typeof n=="string"?i[n]():s.show&&i.show()})},e.fn.modal.defaults={backdrop:!0,keyboard:!0,show:!0},e.fn.modal.Constructor=t,e(document).on("click.modal.data-api",'[data-toggle="modal"]',function(t){var n=e(this),r=n.attr("href"),i=e(n.attr("data-target")||r&&r.replace(/.*(?=#[^\s]+$)/,"")),s=i.data("modal")?"toggle":e.extend({remote:!/#/.test(r)&&r},i.data(),n.data());t.preventDefault(),i.modal(s).one("hide",function(){n.focus()})})}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("tooltip",e,t)};t.prototype={constructor:t,init:function(t,n,r){var i,s;this.type=t,this.$element=e(n),this.options=this.getOptions(r),this.enabled=!0,this.options.trigger=="click"?this.$element.on("click."+this.type,this.options.selector,e.proxy(this.toggle,this)):this.options.trigger!="manual"&&(i=this.options.trigger=="hover"?"mouseenter":"focus",s=this.options.trigger=="hover"?"mouseleave":"blur",this.$element.on(i+"."+this.type,this.options.selector,e.proxy(this.enter,this)),this.$element.on(s+"."+this.type,this.options.selector,e.proxy(this.leave,this))),this.options.selector?this._options=e.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(t){return t=e.extend({},e.fn[this.type].defaults,t,this.$element.data()),t.delay&&typeof t.delay=="number"&&(t.delay={show:t.delay,hide:t.delay}),t},enter:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);if(!n.options.delay||!n.options.delay.show)return n.show();clearTimeout(this.timeout),n.hoverState="in",this.timeout=setTimeout(function(){n.hoverState=="in"&&n.show()},n.options.delay.show)},leave:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);this.timeout&&clearTimeout(this.timeout);if(!n.options.delay||!n.options.delay.hide)return n.hide();n.hoverState="out",this.timeout=setTimeout(function(){n.hoverState=="out"&&n.hide()},n.options.delay.hide)},show:function(){var e,t,n,r,i,s,o;if(this.hasContent()&&this.enabled){e=this.tip(),this.setContent(),this.options.animation&&e.addClass("fade"),s=typeof this.options.placement=="function"?this.options.placement.call(this,e[0],this.$element[0]):this.options.placement,t=/in/.test(s),e.detach().css({top:0,left:0,display:"block"}).insertAfter(this.$element),n=this.getPosition(t),r=e[0].offsetWidth,i=e[0].offsetHeight;switch(t?s.split(" ")[1]:s){case"bottom":o={top:n.top+n.height,left:n.left+n.width/2-r/2};break;case"top":o={top:n.top-i,left:n.left+n.width/2-r/2};break;case"left":o={top:n.top+n.height/2-i/2,left:n.left-r};break;case"right":o={top:n.top+n.height/2-i/2,left:n.left+n.width}}e.offset(o).addClass(s).addClass("in")}},setContent:function(){var e=this.tip(),t=this.getTitle();e.find(".tooltip-inner")[this.options.html?"html":"text"](t),e.removeClass("fade in top bottom left right")},hide:function(){function r(){var t=setTimeout(function(){n.off(e.support.transition.end).detach()},500);n.one(e.support.transition.end,function(){clearTimeout(t),n.detach()})}var t=this,n=this.tip();return n.removeClass("in"),e.support.transition&&this.$tip.hasClass("fade")?r():n.detach(),this},fixTitle:function(){var e=this.$element;(e.attr("title")||typeof e.attr("data-original-title")!="string")&&e.attr("data-original-title",e.attr("title")||"").removeAttr("title")},hasContent:function(){return this.getTitle()},getPosition:function(t){return e.extend({},t?{top:0,left:0}:this.$element.offset(),{width:this.$element[0].offsetWidth,height:this.$element[0].offsetHeight})},getTitle:function(){var e,t=this.$element,n=this.options;return e=t.attr("data-original-title")||(typeof n.title=="function"?n.title.call(t[0]):n.title),e},tip:function(){return this.$tip=this.$tip||e(this.options.template)},validate:function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);n[n.tip().hasClass("in")?"hide":"show"]()},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}},e.fn.tooltip=function(n){return this.each(function(){var r=e(this),i=r.data("tooltip"),s=typeof n=="object"&&n;i||r.data("tooltip",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.tooltip.Constructor=t,e.fn.tooltip.defaults={animation:!0,placement:"top",selector:!1,template:'',trigger:"hover",title:"",delay:0,html:!1}}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("popover",e,t)};t.prototype=e.extend({},e.fn.tooltip.Constructor.prototype,{constructor:t,setContent:function(){var e=this.tip(),t=this.getTitle(),n=this.getContent();e.find(".popover-title")[this.options.html?"html":"text"](t),e.find(".popover-content > *")[this.options.html?"html":"text"](n),e.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var e,t=this.$element,n=this.options;return e=t.attr("data-content")||(typeof n.content=="function"?n.content.call(t[0]):n.content),e},tip:function(){return this.$tip||(this.$tip=e(this.options.template)),this.$tip},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}}),e.fn.popover=function(n){return this.each(function(){var r=e(this),i=r.data("popover"),s=typeof n=="object"&&n;i||r.data("popover",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.popover.Constructor=t,e.fn.popover.defaults=e.extend({},e.fn.tooltip.defaults,{placement:"right",trigger:"click",content:"",template:''})}(window.jQuery),!function(e){"use strict";function t(t,n){var r=e.proxy(this.process,this),i=e(t).is("body")?e(window):e(t),s;this.options=e.extend({},e.fn.scrollspy.defaults,n),this.$scrollElement=i.on("scroll.scroll-spy.data-api",r),this.selector=(this.options.target||(s=e(t).attr("href"))&&s.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.$body=e("body"),this.refresh(),this.process()}t.prototype={constructor:t,refresh:function(){var t=this,n;this.offsets=e([]),this.targets=e([]),n=this.$body.find(this.selector).map(function(){var t=e(this),n=t.data("target")||t.attr("href"),r=/^#\w/.test(n)&&e(n);return r&&r.length&&[[r.position().top,n]]||null}).sort(function(e,t){return e[0]-t[0]}).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},process:function(){var e=this.$scrollElement.scrollTop()+this.options.offset,t=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,n=t-this.$scrollElement.height(),r=this.offsets,i=this.targets,s=this.activeTarget,o;if(e>=n)return s!=(o=i.last()[0])&&this.activate(o);for(o=r.length;o--;)s!=i[o]&&e>=r[o]&&(!r[o+1]||e<=r[o+1])&&this.activate(i[o])},activate:function(t){var n,r;this.activeTarget=t,e(this.selector).parent(".active").removeClass("active"),r=this.selector+'[data-target="'+t+'"],'+this.selector+'[href="'+t+'"]',n=e(r).parent("li").addClass("active"),n.parent(".dropdown-menu").length&&(n=n.closest("li.dropdown").addClass("active")),n.trigger("activate")}},e.fn.scrollspy=function(n){return this.each(function(){var r=e(this),i=r.data("scrollspy"),s=typeof n=="object"&&n;i||r.data("scrollspy",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.scrollspy.Constructor=t,e.fn.scrollspy.defaults={offset:10},e(window).on("load",function(){e('[data-spy="scroll"]').each(function(){var t=e(this);t.scrollspy(t.data())})})}(window.jQuery),!function(e){"use strict";var t=function(t){this.element=e(t)};t.prototype={constructor:t,show:function(){var t=this.element,n=t.closest("ul:not(.dropdown-menu)"),r=t.attr("data-target"),i,s,o;r||(r=t.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,""));if(t.parent("li").hasClass("active"))return;i=n.find(".active:last a")[0],o=e.Event("show",{relatedTarget:i}),t.trigger(o);if(o.isDefaultPrevented())return;s=e(r),this.activate(t.parent("li"),n),this.activate(s,s.parent(),function(){t.trigger({type:"shown",relatedTarget:i})})},activate:function(t,n,r){function o(){i.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),t.addClass("active"),s?(t[0].offsetWidth,t.addClass("in")):t.removeClass("fade"),t.parent(".dropdown-menu")&&t.closest("li.dropdown").addClass("active"),r&&r()}var i=n.find("> .active"),s=r&&e.support.transition&&i.hasClass("fade");s?i.one(e.support.transition.end,o):o(),i.removeClass("in")}},e.fn.tab=function(n){return this.each(function(){var r=e(this),i=r.data("tab");i||r.data("tab",i=new t(this)),typeof n=="string"&&i[n]()})},e.fn.tab.Constructor=t,e(document).on("click.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(t){t.preventDefault(),e(this).tab("show")})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.typeahead.defaults,n),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.$menu=e(this.options.menu).appendTo("body"),this.source=this.options.source,this.shown=!1,this.listen()};t.prototype={constructor:t,select:function(){var e=this.$menu.find(".active").attr("data-value");return this.$element.val(this.updater(e)).change(),this.hide()},updater:function(e){return e},show:function(){var t=e.extend({},this.$element.offset(),{height:this.$element[0].offsetHeight});return this.$menu.css({top:t.top+t.height,left:t.left}),this.$menu.show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(t){var n;return this.query=this.$element.val(),!this.query||this.query.length"+t+""})},render:function(t){var n=this;return t=e(t).map(function(t,r){return t=e(n.options.item).attr("data-value",r),t.find("a").html(n.highlighter(r)),t[0]}),t.first().addClass("active"),this.$menu.html(t),this},next:function(t){var n=this.$menu.find(".active").removeClass("active"),r=n.next();r.length||(r=e(this.$menu.find("li")[0])),r.addClass("active")},prev:function(e){var t=this.$menu.find(".active").removeClass("active"),n=t.prev();n.length||(n=this.$menu.find("li").last()),n.addClass("active")},listen:function(){this.$element.on("blur",e.proxy(this.blur,this)).on("keypress",e.proxy(this.keypress,this)).on("keyup",e.proxy(this.keyup,this)),this.eventSupported("keydown")&&this.$element.on("keydown",e.proxy(this.keydown,this)),this.$menu.on("click",e.proxy(this.click,this)).on("mouseenter","li",e.proxy(this.mouseenter,this))},eventSupported:function(e){var t=e in this.$element;return t||(this.$element.setAttribute(e,"return;"),t=typeof this.$element[e]=="function"),t},move:function(e){if(!this.shown)return;switch(e.keyCode){case 9:case 13:case 27:e.preventDefault();break;case 38:e.preventDefault(),this.prev();break;case 40:e.preventDefault(),this.next()}e.stopPropagation()},keydown:function(t){this.suppressKeyPressRepeat=!~e.inArray(t.keyCode,[40,38,9,13,27]),this.move(t)},keypress:function(e){if(this.suppressKeyPressRepeat)return;this.move(e)},keyup:function(e){switch(e.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}e.stopPropagation(),e.preventDefault()},blur:function(e){var t=this;setTimeout(function(){t.hide()},150)},click:function(e){e.stopPropagation(),e.preventDefault(),this.select()},mouseenter:function(t){this.$menu.find(".active").removeClass("active"),e(t.currentTarget).addClass("active")}},e.fn.typeahead=function(n){return this.each(function(){var r=e(this),i=r.data("typeahead"),s=typeof n=="object"&&n;i||r.data("typeahead",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.typeahead.defaults={source:[],items:8,menu:'',item:' ',minLength:1},e.fn.typeahead.Constructor=t,e(document).on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(t){var n=e(this);if(n.data("typeahead"))return;t.preventDefault(),n.typeahead(n.data())})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=e.extend({},e.fn.affix.defaults,n),this.$window=e(window).on("scroll.affix.data-api",e.proxy(this.checkPosition,this)).on("click.affix.data-api",e.proxy(function(){setTimeout(e.proxy(this.checkPosition,this),1)},this)),this.$element=e(t),this.checkPosition()};t.prototype.checkPosition=function(){if(!this.$element.is(":visible"))return;var t=e(document).height(),n=this.$window.scrollTop(),r=this.$element.offset(),i=this.options.offset,s=i.bottom,o=i.top,u="affix affix-top affix-bottom",a;typeof i!="object"&&(s=o=i),typeof o=="function"&&(o=i.top()),typeof s=="function"&&(s=i.bottom()),a=this.unpin!=null&&n+this.unpin<=r.top?!1:s!=null&&r.top+this.$element.height()>=t-s?"bottom":o!=null&&n<=o?"top":!1;if(this.affixed===a)return;this.affixed=a,this.unpin=a=="bottom"?r.top-n:null,this.$element.removeClass(u).addClass("affix"+(a?"-"+a:""))},e.fn.affix=function(n){return this.each(function(){var r=e(this),i=r.data("affix"),s=typeof n=="object"&&n;i||r.data("affix",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.affix.Constructor=t,e.fn.affix.defaults={offset:0},e(window).on("load",function(){e('[data-spy="affix"]').each(function(){var t=e(this),n=t.data();n.offset=n.offset||{},n.offsetBottom&&(n.offset.bottom=n.offsetBottom),n.offsetTop&&(n.offset.top=n.offsetTop),t.affix(n)})})}(window.jQuery);
--------------------------------------------------------------------------------