projview 0.2.4 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -26,6 +26,25 @@ projview ./docs --port 5000
26
26
  projview /path/to/notes --no-open
27
27
  ```
28
28
 
29
+ ## use it from scripts or an AI
30
+
31
+ projview also has a **machine interface** - subcommands that print JSON to stdout
32
+ and exit (no server, no browser), so an agent or script can query your docs:
33
+
34
+ ```bash
35
+ projview search "<query>" [path] # ranked: filename matches + in-content hits w/ line snippets
36
+ projview tree [path] # the file tree as JSON
37
+ projview search "mermaid" --demo # quick test on the bundled docs
38
+ ```
39
+
40
+ ```jsonc
41
+ // projview search "live reload"
42
+ { "query": "live reload",
43
+ "files": [ /* fuzzy filename matches: {path, name, score} */ ],
44
+ "content": [ { "path": "reference/api.md", "count": 4,
45
+ "snippets": [ { "line": 68, "text": "### live reload" } ] } ] }
46
+ ```
47
+
29
48
  ## what it does
30
49
 
31
50
  | step | detail |
package/bin/projview.js CHANGED
@@ -4,6 +4,8 @@ import { spawn } from 'node:child_process';
4
4
  import { fileURLToPath } from 'node:url';
5
5
  import { readFileSync } from 'node:fs';
6
6
  import { startServer } from '../src/server.js';
7
+ import { buildTree, countFiles } from '../src/walk.js';
8
+ import { buildIndex, search } from '../src/search.js';
7
9
 
8
10
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
11
  const DEMO_DIR = path.join(__dirname, '..', 'docs'); // bundled sample docs
@@ -32,6 +34,33 @@ function parseArgs(argv) {
32
34
  return opts;
33
35
  }
34
36
 
37
+ // --- machine interface: subcommands that print JSON to stdout and exit ---
38
+
39
+ // pick the dir a subcommand runs against: --demo wins, else a positional, else cwd
40
+ function rootFrom(positional, args) {
41
+ if (args.includes('--demo')) return DEMO_DIR;
42
+ return positional[0] ? path.resolve(process.cwd(), positional[0]) : process.cwd();
43
+ }
44
+
45
+ async function cmdSearch(args) {
46
+ const positional = args.filter((a) => !a.startsWith('-'));
47
+ const query = positional[0];
48
+ if (!query) {
49
+ console.error('usage: projview search <query> [path] [--demo]');
50
+ process.exit(1);
51
+ }
52
+ const root = rootFrom(positional.slice(1), args);
53
+ await buildIndex(root);
54
+ process.stdout.write(JSON.stringify(search(query), null, 2) + '\n');
55
+ }
56
+
57
+ function cmdTree(args) {
58
+ const positional = args.filter((a) => !a.startsWith('-'));
59
+ const root = rootFrom(positional, args);
60
+ const tree = buildTree(root);
61
+ process.stdout.write(JSON.stringify({ root: path.basename(root) || root, files: countFiles(tree), tree }, null, 2) + '\n');
62
+ }
63
+
35
64
  function openBrowser(url) {
36
65
  const cmd = process.platform === 'darwin' ? 'open'
37
66
  : process.platform === 'win32' ? 'cmd' : 'xdg-open';
@@ -44,7 +73,12 @@ function openBrowser(url) {
44
73
  const HELP = `projview - ephemeral previewer for markdown + mermaid
45
74
 
46
75
  usage:
47
- projview [path] [options]
76
+ projview [path] [options] start the viewer (default)
77
+ projview search <query> [path] print ranked search results as JSON
78
+ projview tree [path] print the file tree as JSON
79
+
80
+ (subcommands print to stdout and exit - no server. --demo works with them too,
81
+ e.g. projview search "websockets" --demo)
48
82
 
49
83
  arguments:
50
84
  path directory to index (default: current directory)
@@ -59,7 +93,13 @@ options:
59
93
  nothing is written to disk - ctrl-c and it's gone.`;
60
94
 
61
95
  async function main() {
62
- const opts = parseArgs(process.argv.slice(2));
96
+ const argv = process.argv.slice(2);
97
+
98
+ // machine subcommands -> JSON to stdout, then exit (no server)
99
+ if (argv[0] === 'search') return cmdSearch(argv.slice(1));
100
+ if (argv[0] === 'tree') return cmdTree(argv.slice(1));
101
+
102
+ const opts = parseArgs(argv);
63
103
  if (opts.help) { console.log(HELP); return; }
64
104
  if (opts.version) { console.log(VERSION); return; }
65
105
  if (opts.unknown) {
package/docs/README.md CHANGED
@@ -21,6 +21,7 @@ faults. use this tree while iterating on the tool.
21
21
  | edge | [syntax stress](edge-cases/syntax-stress.md) | gnarly markdown + inline broken fence |
22
22
  | edge | [faulty refs](edge-cases/faulty-refs.md) | **several dead links** on purpose |
23
23
  | edge | [buried file](edge-cases/deep/nested/buried.md) | deep nesting - indentation + auto-expand |
24
+ | ai-tests | [search test](ai-tests/search.md) | AI-run test of the `projview search` machine interface |
24
25
 
25
26
  ## intentional faults (should NOT crash the app)
26
27
 
@@ -0,0 +1,120 @@
1
+ # search functionality - AI test
2
+
3
+ An AI-driven test of projview's `search` **machine interface** (`projview search
4
+ <query>` → JSON on stdout). The goal: probe distinct behaviours of the engine -
5
+ content search, fuzzy filenames, multi-term logic, ranking, and edge cases - by
6
+ running the published CLI and inspecting the JSON it returns.
7
+
8
+ ## experimental parameters
9
+
10
+ | parameter | value |
11
+ | --- | --- |
12
+ | tool | `projview` (global install) |
13
+ | version | `0.4.0` |
14
+ | command form | `projview search "<query>" --demo` |
15
+ | dataset | the bundled demo docs (`--demo`) - **14 files** at time of test |
16
+ | output | JSON: `{ query, files[], content[] }` parsed from stdout |
17
+ | ranking | filenames by fuzzy subsequence score; contents by term frequency |
18
+
19
+ > Note: this very report is the 15th file in the set, so re-running the probes
20
+ > below will now also surface `ai-tests/search.md` itself.
21
+
22
+ ## method
23
+
24
+ Five search terms were chosen, each targeting a different aspect of the engine:
25
+
26
+ | # | term | aspect under test |
27
+ | --- | --- | --- |
28
+ | 1 | `live reload` | content search across multiple files + snippet line numbers |
29
+ | 2 | `mermaid` | frequency ranking + case-insensitivity (`MERMAID` vs `mermaid`) |
30
+ | 3 | `cfg` | fuzzy **filename** match (subsequence), independent of content |
31
+ | 4 | `broken diagram` | multi-term **AND** logic + cross-file ranking |
32
+ | 5 | `kubernetes` | graceful **no-match** behaviour |
33
+
34
+ ## results
35
+
36
+ ### 1. content search - `live reload`
37
+
38
+ ```bash
39
+ projview search "live reload" --demo
40
+ ```
41
+
42
+ Three files matched, ranked by frequency, each snippet carrying a line number:
43
+
44
+ | file | hits | top snippet |
45
+ | --- | --- | --- |
46
+ | `reference/api.md` | 4 | L68 `### live reload` |
47
+ | `diagrams/sequence.mmd` | 2 | L13 `edit a file -> SSE -> live reload` |
48
+ | `reference/glossary.md` | 2 | L9 `live reload - SSE-driven refresh` |
49
+
50
+ ✅ Multi-file content search, frequency-ordered, with usable `file:line` citations.
51
+
52
+ ### 2. ranking + case-insensitivity - `mermaid`
53
+
54
+ `mermaid` returned **8** content matches. Crucially, `MERMAID` (uppercase)
55
+ returned the **same 8** - the query is lower-cased before matching.
56
+
57
+ ✅ Case-insensitive; ranked by occurrence count.
58
+
59
+ ### 3. fuzzy filename match - `cfg`
60
+
61
+ ```bash
62
+ projview search "cfg" --demo
63
+ # files: ["guides/configuration.md"]
64
+ # content: (none)
65
+ ```
66
+
67
+ `cfg` is not a substring of any document body, but it **is** a subsequence of
68
+ `configuration.md`, so it surfaces in the `files` block while `content` stays empty.
69
+
70
+ ✅ Filename matching is fuzzy (subsequence) and independent of content search.
71
+
72
+ ### 4. multi-term AND + ranking - `broken diagram`
73
+
74
+ ```bash
75
+ projview search "broken diagram" --demo
76
+ ```
77
+
78
+ | file | hits |
79
+ | --- | --- |
80
+ | `README.md` | 12 |
81
+ | `guides/troubleshooting.md` | 7 |
82
+ | `edge-cases/syntax-stress.md` | 6 |
83
+ | `guides/configuration.md` | 3 |
84
+ | `edge-cases/faulty-refs.md` | 2 |
85
+
86
+ Only files containing **both** terms appear; ranking is by total term frequency.
87
+
88
+ ✅ Multi-term is a **file-level AND** (every term must appear somewhere in the
89
+ file), ranked by combined frequency.
90
+
91
+ ### 5. graceful no-match - `kubernetes`
92
+
93
+ ```bash
94
+ projview search "kubernetes" --demo
95
+ # { "query": "kubernetes", "files": [], "content": [] }
96
+ ```
97
+
98
+ ✅ Empty arrays, exit code `0` - a clean "nothing found", not an error.
99
+
100
+ ## observations & limitations
101
+
102
+ - **Case-insensitive** matching (query is lower-cased).
103
+ - **Multi-term = file-level AND**, not phrase match - the words can be anywhere in
104
+ the file, ranked by total frequency.
105
+ - **Snippets are first-occurrence**: the shown snippet is the first line containing
106
+ *any* query term, which isn't always the most relevant line for multi-term
107
+ queries. (A future improvement: prefer lines matching the most terms.)
108
+ - **Two independent result blocks**: `files` (fuzzy filename) and `content`
109
+ (full-text) - either can be populated without the other.
110
+
111
+ ## reproduce
112
+
113
+ ```bash
114
+ npm i -g projview@latest
115
+ projview search "live reload" --demo
116
+ projview search "cfg" --demo
117
+ projview search "broken diagram" --demo
118
+ projview search "kubernetes" --demo
119
+ projview tree --demo # list the dataset
120
+ ```
@@ -66,7 +66,7 @@ npm install
66
66
  npm run demo # preview the bundled docs/ (alias for --demo)
67
67
  npm start # index the current directory
68
68
  node bin/projview.js ./docs # or call the CLI directly
69
- npm test # run the test suite (node:test, 23 tests)
69
+ npm test # run the test suite (node:test, 29 tests)
70
70
  ```
71
71
 
72
72
  See the [project README](README.md) for the architecture and the
@@ -74,12 +74,27 @@ See the [project README](README.md) for the architecture and the
74
74
 
75
75
  ## CLI reference
76
76
 
77
+ **Commands**
78
+
79
+ | command | meaning |
80
+ | --- | --- |
81
+ | `projview [path]` | start the viewer (default) |
82
+ | `projview search <query> [path]` | print ranked search results as JSON, then exit |
83
+ | `projview tree [path]` | print the file tree as JSON, then exit |
84
+
85
+ The `search` and `tree` subcommands are projview's **machine interface** - JSON on
86
+ stdout, no server, no browser - built for agents and scripts. See
87
+ [ai-tests/search.md](ai-tests/search.md) for a worked test.
88
+
89
+ **Options**
90
+
77
91
  | argument / flag | meaning |
78
92
  | --- | --- |
79
93
  | `[path]` | directory to index (default: current directory) |
80
- | `--demo` | preview projview's own bundled sample docs |
94
+ | `--demo` | use projview's own bundled sample docs (works with the subcommands too) |
81
95
  | `-p`, `--port <n>` | preferred port (default `4321`, climbs if taken) |
82
96
  | `--no-open` | don't auto-open the browser |
97
+ | `-v`, `--version` | print the version and exit |
83
98
  | `-h`, `--help` | show help |
84
99
 
85
100
  **Environment variables** (handy for containers / servers):
@@ -21,6 +21,22 @@ Renders a single file to HTML on demand. Query param `p` is the relative path.
21
21
 
22
22
  Server-sent events stream for live reload.
23
23
 
24
+ ## machine interface (CLI)
25
+
26
+ Besides the HTTP server, two subcommands print JSON to stdout and exit - no
27
+ server, no browser - for agents and scripts.
28
+
29
+ ### projview search
30
+
31
+ `projview search "<query>" [path]` returns `{ query, files[], content[] }`.
32
+ Filenames match fuzzily (subsequence); contents are ranked by term frequency with
33
+ line-numbered snippets. See [the AI search test](../ai-tests/search.md).
34
+
35
+ ### projview tree
36
+
37
+ `projview tree [path]` returns `{ root, files, tree[] }` - the same structure
38
+ `/api/tree` serves.
39
+
24
40
  ## the walker
25
41
 
26
42
  ### ignored directories
@@ -59,7 +75,7 @@ Requested paths are resolved and confined to the root.
59
75
 
60
76
  ### tree nav
61
77
 
62
- Collapsible dirs, filter box, auto-expand on navigate.
78
+ Collapsible dirs, cmd+K search palette, auto-expand on navigate.
63
79
 
64
80
  ### viewer
65
81
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "projview",
3
- "version": "0.2.4",
3
+ "version": "0.4.1",
4
4
  "description": "Ephemeral local previewer for markdown + mermaid files in any directory",
5
5
  "type": "module",
6
6
  "bin": {
@@ -41,5 +41,8 @@
41
41
  "chokidar": "^4.0.3",
42
42
  "highlight.js": "^11.11.1",
43
43
  "markdown-it": "^14.1.0"
44
+ },
45
+ "devDependencies": {
46
+ "svg-pan-zoom": "^3.6.2"
44
47
  }
45
48
  }
package/public/index.html CHANGED
@@ -75,6 +75,7 @@
75
75
  </div>
76
76
 
77
77
  <script src="/vendor/mermaid.min.js"></script>
78
+ <script src="/vendor/svg-pan-zoom.min.js"></script>
78
79
  <script type="module" src="/main.js"></script>
79
80
  </body>
80
81
  </html>
package/public/mermaid.js CHANGED
@@ -38,40 +38,48 @@ export async function runMermaid() {
38
38
  }
39
39
  }
40
40
 
41
- /* ---------- zoom overlay ---------- */
41
+ /* ---------- zoom overlay (svg-pan-zoom: crisp vector zoom, pan, control bar) ---------- */
42
42
 
43
- let zoomState = { scale: 1, x: 0, y: 0 };
44
- let zoomDrag = null;
43
+ const svgPanZoom = window.svgPanZoom; // UMD global from /vendor/svg-pan-zoom.min.js
44
+ let panzoom = null; // active instance, if any
45
45
 
46
- function applyZoom() {
47
- zoomInnerEl.style.transform =
48
- `translate(${zoomState.x}px, ${zoomState.y}px) scale(${zoomState.scale})`;
49
- }
50
46
  function openZoom(svgHtml) {
51
47
  if (!svgHtml) return;
52
48
  zoomInnerEl.innerHTML = svgHtml;
53
- zoomState = { scale: 1, x: 0, y: 0 };
54
- applyZoom();
49
+ const svg = zoomInnerEl.querySelector('svg');
50
+ if (!svg) return;
51
+
52
+ // hand sizing to svg-pan-zoom: fill the stage and drop mermaid's max-width cap,
53
+ // so zoom stays vector-crisp (no rasterised CSS-transform blur)
54
+ svg.removeAttribute('width');
55
+ svg.removeAttribute('height');
56
+ svg.style.maxWidth = 'none';
57
+ svg.style.width = '100%';
58
+ svg.style.height = '100%';
59
+
55
60
  zoomEl.hidden = false;
61
+ // wait two frames so the just-shown overlay is laid out before svg-pan-zoom
62
+ // measures it - a single rAF fires too early and it inits on a 0-size stage
63
+ requestAnimationFrame(() => requestAnimationFrame(() => {
64
+ if (zoomEl.hidden || !svg.isConnected) return; // closed again before we got here
65
+ panzoom = svgPanZoom(svg, {
66
+ zoomEnabled: true,
67
+ panEnabled: true,
68
+ controlIconsEnabled: true, // built-in zoom in / out / reset / fit bar
69
+ fit: true,
70
+ center: true,
71
+ minZoom: 0.2,
72
+ maxZoom: 30,
73
+ zoomScaleSensitivity: 0.3
74
+ });
75
+ }));
76
+ }
77
+
78
+ function closeZoom() {
79
+ if (panzoom) { panzoom.destroy(); panzoom = null; }
80
+ zoomEl.hidden = true;
81
+ zoomInnerEl.innerHTML = '';
56
82
  }
57
- function closeZoom() { zoomEl.hidden = true; zoomInnerEl.innerHTML = ''; }
58
83
 
59
84
  zoomEl.addEventListener('click', (e) => { if (e.target === zoomEl) closeZoom(); });
60
- zoomEl.addEventListener('wheel', (e) => {
61
- e.preventDefault();
62
- const factor = e.deltaY < 0 ? 1.12 : 1 / 1.12;
63
- zoomState.scale = Math.min(8, Math.max(0.3, zoomState.scale * factor));
64
- applyZoom();
65
- }, { passive: false });
66
- zoomInnerEl.addEventListener('pointerdown', (e) => {
67
- zoomDrag = { x: e.clientX, y: e.clientY, ox: zoomState.x, oy: zoomState.y };
68
- zoomInnerEl.setPointerCapture(e.pointerId);
69
- });
70
- zoomInnerEl.addEventListener('pointermove', (e) => {
71
- if (!zoomDrag) return;
72
- zoomState.x = zoomDrag.ox + (e.clientX - zoomDrag.x);
73
- zoomState.y = zoomDrag.oy + (e.clientY - zoomDrag.y);
74
- applyZoom();
75
- });
76
- zoomInnerEl.addEventListener('pointerup', () => { zoomDrag = null; });
77
85
  window.addEventListener('keydown', (e) => { if (e.key === 'Escape' && !zoomEl.hidden) closeZoom(); });
package/public/style.css CHANGED
@@ -519,13 +519,11 @@ mark.search-hit {
519
519
  border: 1px solid var(--surface0);
520
520
  }
521
521
  .zoom-inner {
522
- cursor: grab;
523
- transform-origin: center center;
524
- will-change: transform;
525
- touch-action: none;
522
+ width: 88vw;
523
+ height: 84vh;
524
+ touch-action: none; /* svg-pan-zoom owns the gestures */
526
525
  }
527
- .zoom-inner:active { cursor: grabbing; }
528
- .zoom-inner svg { max-width: 86vw; max-height: 82vh; }
526
+ .zoom-inner svg { width: 100%; height: 100%; display: block; }
529
527
 
530
528
  /* scrollbars */
531
529
  ::-webkit-scrollbar { width: 11px; height: 11px; }
@@ -0,0 +1,3 @@
1
+ // svg-pan-zoom v3.6.2
2
+ // https://github.com/bumbu/svg-pan-zoom
3
+ !function s(r,a,l){function u(e,t){if(!a[e]){if(!r[e]){var o="function"==typeof require&&require;if(!t&&o)return o(e,!0);if(h)return h(e,!0);var n=new Error("Cannot find module '"+e+"'");throw n.code="MODULE_NOT_FOUND",n}var i=a[e]={exports:{}};r[e][0].call(i.exports,function(t){return u(r[e][1][t]||t)},i,i.exports,s,r,a,l)}return a[e].exports}for(var h="function"==typeof require&&require,t=0;t<l.length;t++)u(l[t]);return u}({1:[function(t,e,o){var s=t("./svg-utilities");e.exports={enable:function(t){var e=t.svg.querySelector("defs");if(e||(e=document.createElementNS(s.svgNS,"defs"),t.svg.appendChild(e)),!e.querySelector("style#svg-pan-zoom-controls-styles")){var o=document.createElementNS(s.svgNS,"style");o.setAttribute("id","svg-pan-zoom-controls-styles"),o.setAttribute("type","text/css"),o.textContent=".svg-pan-zoom-control { cursor: pointer; fill: black; fill-opacity: 0.333; } .svg-pan-zoom-control:hover { fill-opacity: 0.8; } .svg-pan-zoom-control-background { fill: white; fill-opacity: 0.5; } .svg-pan-zoom-control-background { fill-opacity: 0.8; }",e.appendChild(o)}var n=document.createElementNS(s.svgNS,"g");n.setAttribute("id","svg-pan-zoom-controls"),n.setAttribute("transform","translate("+(t.width-70)+" "+(t.height-76)+") scale(0.75)"),n.setAttribute("class","svg-pan-zoom-control"),n.appendChild(this._createZoomIn(t)),n.appendChild(this._createZoomReset(t)),n.appendChild(this._createZoomOut(t)),t.svg.appendChild(n),t.controlIcons=n},_createZoomIn:function(t){var e=document.createElementNS(s.svgNS,"g");e.setAttribute("id","svg-pan-zoom-zoom-in"),e.setAttribute("transform","translate(30.5 5) scale(0.015)"),e.setAttribute("class","svg-pan-zoom-control"),e.addEventListener("click",function(){t.getPublicInstance().zoomIn()},!1),e.addEventListener("touchstart",function(){t.getPublicInstance().zoomIn()},!1);var o=document.createElementNS(s.svgNS,"rect");o.setAttribute("x","0"),o.setAttribute("y","0"),o.setAttribute("width","1500"),o.setAttribute("height","1400"),o.setAttribute("class","svg-pan-zoom-control-background"),e.appendChild(o);var n=document.createElementNS(s.svgNS,"path");return n.setAttribute("d","M1280 576v128q0 26 -19 45t-45 19h-320v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-320q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h320v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h320q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z"),n.setAttribute("class","svg-pan-zoom-control-element"),e.appendChild(n),e},_createZoomReset:function(t){var e=document.createElementNS(s.svgNS,"g");e.setAttribute("id","svg-pan-zoom-reset-pan-zoom"),e.setAttribute("transform","translate(5 35) scale(0.4)"),e.setAttribute("class","svg-pan-zoom-control"),e.addEventListener("click",function(){t.getPublicInstance().reset()},!1),e.addEventListener("touchstart",function(){t.getPublicInstance().reset()},!1);var o=document.createElementNS(s.svgNS,"rect");o.setAttribute("x","2"),o.setAttribute("y","2"),o.setAttribute("width","182"),o.setAttribute("height","58"),o.setAttribute("class","svg-pan-zoom-control-background"),e.appendChild(o);var n=document.createElementNS(s.svgNS,"path");n.setAttribute("d","M33.051,20.632c-0.742-0.406-1.854-0.609-3.338-0.609h-7.969v9.281h7.769c1.543,0,2.701-0.188,3.473-0.562c1.365-0.656,2.048-1.953,2.048-3.891C35.032,22.757,34.372,21.351,33.051,20.632z"),n.setAttribute("class","svg-pan-zoom-control-element"),e.appendChild(n);var i=document.createElementNS(s.svgNS,"path");return i.setAttribute("d","M170.231,0.5H15.847C7.102,0.5,0.5,5.708,0.5,11.84v38.861C0.5,56.833,7.102,61.5,15.847,61.5h154.384c8.745,0,15.269-4.667,15.269-10.798V11.84C185.5,5.708,178.976,0.5,170.231,0.5z M42.837,48.569h-7.969c-0.219-0.766-0.375-1.383-0.469-1.852c-0.188-0.969-0.289-1.961-0.305-2.977l-0.047-3.211c-0.03-2.203-0.41-3.672-1.142-4.406c-0.732-0.734-2.103-1.102-4.113-1.102h-7.05v13.547h-7.055V14.022h16.524c2.361,0.047,4.178,0.344,5.45,0.891c1.272,0.547,2.351,1.352,3.234,2.414c0.731,0.875,1.31,1.844,1.737,2.906s0.64,2.273,0.64,3.633c0,1.641-0.414,3.254-1.242,4.84s-2.195,2.707-4.102,3.363c1.594,0.641,2.723,1.551,3.387,2.73s0.996,2.98,0.996,5.402v2.32c0,1.578,0.063,2.648,0.19,3.211c0.19,0.891,0.635,1.547,1.333,1.969V48.569z M75.579,48.569h-26.18V14.022h25.336v6.117H56.454v7.336h16.781v6H56.454v8.883h19.125V48.569z M104.497,46.331c-2.44,2.086-5.887,3.129-10.34,3.129c-4.548,0-8.125-1.027-10.731-3.082s-3.909-4.879-3.909-8.473h6.891c0.224,1.578,0.662,2.758,1.316,3.539c1.196,1.422,3.246,2.133,6.15,2.133c1.739,0,3.151-0.188,4.236-0.562c2.058-0.719,3.087-2.055,3.087-4.008c0-1.141-0.504-2.023-1.512-2.648c-1.008-0.609-2.607-1.148-4.796-1.617l-3.74-0.82c-3.676-0.812-6.201-1.695-7.576-2.648c-2.328-1.594-3.492-4.086-3.492-7.477c0-3.094,1.139-5.664,3.417-7.711s5.623-3.07,10.036-3.07c3.685,0,6.829,0.965,9.431,2.895c2.602,1.93,3.966,4.73,4.093,8.402h-6.938c-0.128-2.078-1.057-3.555-2.787-4.43c-1.154-0.578-2.587-0.867-4.301-0.867c-1.907,0-3.428,0.375-4.565,1.125c-1.138,0.75-1.706,1.797-1.706,3.141c0,1.234,0.561,2.156,1.682,2.766c0.721,0.406,2.25,0.883,4.589,1.43l6.063,1.43c2.657,0.625,4.648,1.461,5.975,2.508c2.059,1.625,3.089,3.977,3.089,7.055C108.157,41.624,106.937,44.245,104.497,46.331z M139.61,48.569h-26.18V14.022h25.336v6.117h-18.281v7.336h16.781v6h-16.781v8.883h19.125V48.569z M170.337,20.14h-10.336v28.43h-7.266V20.14h-10.383v-6.117h27.984V20.14z"),i.setAttribute("class","svg-pan-zoom-control-element"),e.appendChild(i),e},_createZoomOut:function(t){var e=document.createElementNS(s.svgNS,"g");e.setAttribute("id","svg-pan-zoom-zoom-out"),e.setAttribute("transform","translate(30.5 70) scale(0.015)"),e.setAttribute("class","svg-pan-zoom-control"),e.addEventListener("click",function(){t.getPublicInstance().zoomOut()},!1),e.addEventListener("touchstart",function(){t.getPublicInstance().zoomOut()},!1);var o=document.createElementNS(s.svgNS,"rect");o.setAttribute("x","0"),o.setAttribute("y","0"),o.setAttribute("width","1500"),o.setAttribute("height","1400"),o.setAttribute("class","svg-pan-zoom-control-background"),e.appendChild(o);var n=document.createElementNS(s.svgNS,"path");return n.setAttribute("d","M1280 576v128q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h896q26 0 45 19t19 45zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5 t84.5 -203.5z"),n.setAttribute("class","svg-pan-zoom-control-element"),e.appendChild(n),e},disable:function(t){t.controlIcons&&(t.controlIcons.parentNode.removeChild(t.controlIcons),t.controlIcons=null)}}},{"./svg-utilities":5}],2:[function(t,e,o){function n(t,e){this.init(t,e)}var i=t("./svg-utilities"),r=t("./utilities");n.prototype.init=function(t,e){this.viewport=t,this.options=e,this.originalState={zoom:1,x:0,y:0},this.activeState={zoom:1,x:0,y:0},this.updateCTMCached=r.proxy(this.updateCTM,this),this.requestAnimationFrame=r.createRequestAnimationFrame(this.options.refreshRate),this.viewBox={x:0,y:0,width:0,height:0},this.cacheViewBox();var o=this.processCTM();this.setCTM(o),this.updateCTM()},n.prototype.cacheViewBox=function(){var t=this.options.svg.getAttribute("viewBox");if(t){var e=t.split(/[\s\,]/).filter(function(t){return t}).map(parseFloat);this.viewBox.x=e[0],this.viewBox.y=e[1],this.viewBox.width=e[2],this.viewBox.height=e[3];var o=Math.min(this.options.width/this.viewBox.width,this.options.height/this.viewBox.height);this.activeState.zoom=o,this.activeState.x=(this.options.width-this.viewBox.width*o)/2,this.activeState.y=(this.options.height-this.viewBox.height*o)/2,this.updateCTMOnNextFrame(),this.options.svg.removeAttribute("viewBox")}else this.simpleViewBoxCache()},n.prototype.simpleViewBoxCache=function(){var t=this.viewport.getBBox();this.viewBox.x=t.x,this.viewBox.y=t.y,this.viewBox.width=t.width,this.viewBox.height=t.height},n.prototype.getViewBox=function(){return r.extend({},this.viewBox)},n.prototype.processCTM=function(){var t,e=this.getCTM();(this.options.fit||this.options.contain)&&(t=this.options.fit?Math.min(this.options.width/this.viewBox.width,this.options.height/this.viewBox.height):Math.max(this.options.width/this.viewBox.width,this.options.height/this.viewBox.height),e.a=t,e.d=t,e.e=-this.viewBox.x*t,e.f=-this.viewBox.y*t);if(this.options.center){var o=.5*(this.options.width-(this.viewBox.width+2*this.viewBox.x)*e.a),n=.5*(this.options.height-(this.viewBox.height+2*this.viewBox.y)*e.a);e.e=o,e.f=n}return this.originalState.zoom=e.a,this.originalState.x=e.e,this.originalState.y=e.f,e},n.prototype.getOriginalState=function(){return r.extend({},this.originalState)},n.prototype.getState=function(){return r.extend({},this.activeState)},n.prototype.getZoom=function(){return this.activeState.zoom},n.prototype.getRelativeZoom=function(){return this.activeState.zoom/this.originalState.zoom},n.prototype.computeRelativeZoom=function(t){return t/this.originalState.zoom},n.prototype.getPan=function(){return{x:this.activeState.x,y:this.activeState.y}},n.prototype.getCTM=function(){var t=this.options.svg.createSVGMatrix();return t.a=this.activeState.zoom,t.b=0,t.c=0,t.d=this.activeState.zoom,t.e=this.activeState.x,t.f=this.activeState.y,t},n.prototype.setCTM=function(t){var e=this.isZoomDifferent(t),o=this.isPanDifferent(t);if(e||o){if(e&&(!1===this.options.beforeZoom(this.getRelativeZoom(),this.computeRelativeZoom(t.a))?(t.a=t.d=this.activeState.zoom,e=!1):(this.updateCache(t),this.options.onZoom(this.getRelativeZoom()))),o){var n=this.options.beforePan(this.getPan(),{x:t.e,y:t.f}),i=!1,s=!1;!1===n?(t.e=this.getPan().x,t.f=this.getPan().y,i=s=!0):r.isObject(n)&&(!1===n.x?(t.e=this.getPan().x,i=!0):r.isNumber(n.x)&&(t.e=n.x),!1===n.y?(t.f=this.getPan().y,s=!0):r.isNumber(n.y)&&(t.f=n.y)),i&&s||!this.isPanDifferent(t)?o=!1:(this.updateCache(t),this.options.onPan(this.getPan()))}(e||o)&&this.updateCTMOnNextFrame()}},n.prototype.isZoomDifferent=function(t){return this.activeState.zoom!==t.a},n.prototype.isPanDifferent=function(t){return this.activeState.x!==t.e||this.activeState.y!==t.f},n.prototype.updateCache=function(t){this.activeState.zoom=t.a,this.activeState.x=t.e,this.activeState.y=t.f},n.prototype.pendingUpdate=!1,n.prototype.updateCTMOnNextFrame=function(){this.pendingUpdate||(this.pendingUpdate=!0,this.requestAnimationFrame.call(window,this.updateCTMCached))},n.prototype.updateCTM=function(){var t=this.getCTM();i.setCTM(this.viewport,t,this.defs),this.pendingUpdate=!1,this.options.onUpdatedCTM&&this.options.onUpdatedCTM(t)},e.exports=function(t,e){return new n(t,e)}},{"./svg-utilities":5,"./utilities":7}],3:[function(t,e,o){var n,i=t("./svg-pan-zoom.js");n=window,document,"function"==typeof define&&define.amd?define("svg-pan-zoom",function(){return i}):void 0!==e&&e.exports&&(e.exports=i,n.svgPanZoom=i)},{"./svg-pan-zoom.js":4}],4:[function(t,e,o){function i(t,e){this.init(t,e)}var n=t("./uniwheel"),s=t("./control-icons"),r=t("./utilities"),a=t("./svg-utilities"),l=t("./shadow-viewport"),u={viewportSelector:".svg-pan-zoom_viewport",panEnabled:!0,controlIconsEnabled:!1,zoomEnabled:!0,dblClickZoomEnabled:!0,mouseWheelZoomEnabled:!0,preventMouseEventsDefault:!0,zoomScaleSensitivity:.1,minZoom:.5,maxZoom:10,fit:!0,contain:!1,center:!0,refreshRate:"auto",beforeZoom:null,onZoom:null,beforePan:null,onPan:null,customEventsHandler:null,eventsListenerElement:null,onUpdatedCTM:null},h={passive:!0};i.prototype.init=function(t,e){var o=this;this.svg=t,this.defs=t.querySelector("defs"),a.setupSvgAttributes(this.svg),this.options=r.extend(r.extend({},u),e),this.state="none";var n=a.getBoundingClientRectNormalized(t);this.width=n.width,this.height=n.height,this.viewport=l(a.getOrCreateViewport(this.svg,this.options.viewportSelector),{svg:this.svg,width:this.width,height:this.height,fit:this.options.fit,contain:this.options.contain,center:this.options.center,refreshRate:this.options.refreshRate,beforeZoom:function(t,e){if(o.viewport&&o.options.beforeZoom)return o.options.beforeZoom(t,e)},onZoom:function(t){if(o.viewport&&o.options.onZoom)return o.options.onZoom(t)},beforePan:function(t,e){if(o.viewport&&o.options.beforePan)return o.options.beforePan(t,e)},onPan:function(t){if(o.viewport&&o.options.onPan)return o.options.onPan(t)},onUpdatedCTM:function(t){if(o.viewport&&o.options.onUpdatedCTM)return o.options.onUpdatedCTM(t)}});var i=this.getPublicInstance();i.setBeforeZoom(this.options.beforeZoom),i.setOnZoom(this.options.onZoom),i.setBeforePan(this.options.beforePan),i.setOnPan(this.options.onPan),i.setOnUpdatedCTM(this.options.onUpdatedCTM),this.options.controlIconsEnabled&&s.enable(this),this.lastMouseWheelEventTime=Date.now(),this.setupHandlers()},i.prototype.setupHandlers=function(){var o=this,n=null;if(this.eventListeners={mousedown:function(t){var e=o.handleMouseDown(t,n);return n=t,e},touchstart:function(t){var e=o.handleMouseDown(t,n);return n=t,e},mouseup:function(t){return o.handleMouseUp(t)},touchend:function(t){return o.handleMouseUp(t)},mousemove:function(t){return o.handleMouseMove(t)},touchmove:function(t){return o.handleMouseMove(t)},mouseleave:function(t){return o.handleMouseUp(t)},touchleave:function(t){return o.handleMouseUp(t)},touchcancel:function(t){return o.handleMouseUp(t)}},null!=this.options.customEventsHandler){this.options.customEventsHandler.init({svgElement:this.svg,eventsListenerElement:this.options.eventsListenerElement,instance:this.getPublicInstance()});var t=this.options.customEventsHandler.haltEventListeners;if(t&&t.length)for(var e=t.length-1;0<=e;e--)this.eventListeners.hasOwnProperty(t[e])&&delete this.eventListeners[t[e]]}for(var i in this.eventListeners)(this.options.eventsListenerElement||this.svg).addEventListener(i,this.eventListeners[i],!this.options.preventMouseEventsDefault&&h);this.options.mouseWheelZoomEnabled&&(this.options.mouseWheelZoomEnabled=!1,this.enableMouseWheelZoom())},i.prototype.enableMouseWheelZoom=function(){if(!this.options.mouseWheelZoomEnabled){var e=this;this.wheelListener=function(t){return e.handleMouseWheel(t)};var t=!this.options.preventMouseEventsDefault;n.on(this.options.eventsListenerElement||this.svg,this.wheelListener,t),this.options.mouseWheelZoomEnabled=!0}},i.prototype.disableMouseWheelZoom=function(){if(this.options.mouseWheelZoomEnabled){var t=!this.options.preventMouseEventsDefault;n.off(this.options.eventsListenerElement||this.svg,this.wheelListener,t),this.options.mouseWheelZoomEnabled=!1}},i.prototype.handleMouseWheel=function(t){if(this.options.zoomEnabled&&"none"===this.state){this.options.preventMouseEventsDefault&&(t.preventDefault?t.preventDefault():t.returnValue=!1);var e=t.deltaY||1,o=Date.now()-this.lastMouseWheelEventTime,n=3+Math.max(0,30-o);this.lastMouseWheelEventTime=Date.now(),"deltaMode"in t&&0===t.deltaMode&&t.wheelDelta&&(e=0===t.deltaY?0:Math.abs(t.wheelDelta)/t.deltaY),e=-.3<e&&e<.3?e:(0<e?1:-1)*Math.log(Math.abs(e)+10)/n;var i=this.svg.getScreenCTM().inverse(),s=a.getEventPoint(t,this.svg).matrixTransform(i),r=Math.pow(1+this.options.zoomScaleSensitivity,-1*e);this.zoomAtPoint(r,s)}},i.prototype.zoomAtPoint=function(t,e,o){var n=this.viewport.getOriginalState();o?(t=Math.max(this.options.minZoom*n.zoom,Math.min(this.options.maxZoom*n.zoom,t)),t/=this.getZoom()):this.getZoom()*t<this.options.minZoom*n.zoom?t=this.options.minZoom*n.zoom/this.getZoom():this.getZoom()*t>this.options.maxZoom*n.zoom&&(t=this.options.maxZoom*n.zoom/this.getZoom());var i=this.viewport.getCTM(),s=e.matrixTransform(i.inverse()),r=this.svg.createSVGMatrix().translate(s.x,s.y).scale(t).translate(-s.x,-s.y),a=i.multiply(r);a.a!==i.a&&this.viewport.setCTM(a)},i.prototype.zoom=function(t,e){this.zoomAtPoint(t,a.getSvgCenterPoint(this.svg,this.width,this.height),e)},i.prototype.publicZoom=function(t,e){e&&(t=this.computeFromRelativeZoom(t)),this.zoom(t,e)},i.prototype.publicZoomAtPoint=function(t,e,o){if(o&&(t=this.computeFromRelativeZoom(t)),"SVGPoint"!==r.getType(e)){if(!("x"in e&&"y"in e))throw new Error("Given point is invalid");e=a.createSVGPoint(this.svg,e.x,e.y)}this.zoomAtPoint(t,e,o)},i.prototype.getZoom=function(){return this.viewport.getZoom()},i.prototype.getRelativeZoom=function(){return this.viewport.getRelativeZoom()},i.prototype.computeFromRelativeZoom=function(t){return t*this.viewport.getOriginalState().zoom},i.prototype.resetZoom=function(){var t=this.viewport.getOriginalState();this.zoom(t.zoom,!0)},i.prototype.resetPan=function(){this.pan(this.viewport.getOriginalState())},i.prototype.reset=function(){this.resetZoom(),this.resetPan()},i.prototype.handleDblClick=function(t){var e;if((this.options.preventMouseEventsDefault&&(t.preventDefault?t.preventDefault():t.returnValue=!1),this.options.controlIconsEnabled)&&-1<(t.target.getAttribute("class")||"").indexOf("svg-pan-zoom-control"))return!1;e=t.shiftKey?1/(2*(1+this.options.zoomScaleSensitivity)):2*(1+this.options.zoomScaleSensitivity);var o=a.getEventPoint(t,this.svg).matrixTransform(this.svg.getScreenCTM().inverse());this.zoomAtPoint(e,o)},i.prototype.handleMouseDown=function(t,e){this.options.preventMouseEventsDefault&&(t.preventDefault?t.preventDefault():t.returnValue=!1),r.mouseAndTouchNormalize(t,this.svg),this.options.dblClickZoomEnabled&&r.isDblClick(t,e)?this.handleDblClick(t):(this.state="pan",this.firstEventCTM=this.viewport.getCTM(),this.stateOrigin=a.getEventPoint(t,this.svg).matrixTransform(this.firstEventCTM.inverse()))},i.prototype.handleMouseMove=function(t){if(this.options.preventMouseEventsDefault&&(t.preventDefault?t.preventDefault():t.returnValue=!1),"pan"===this.state&&this.options.panEnabled){var e=a.getEventPoint(t,this.svg).matrixTransform(this.firstEventCTM.inverse()),o=this.firstEventCTM.translate(e.x-this.stateOrigin.x,e.y-this.stateOrigin.y);this.viewport.setCTM(o)}},i.prototype.handleMouseUp=function(t){this.options.preventMouseEventsDefault&&(t.preventDefault?t.preventDefault():t.returnValue=!1),"pan"===this.state&&(this.state="none")},i.prototype.fit=function(){var t=this.viewport.getViewBox(),e=Math.min(this.width/t.width,this.height/t.height);this.zoom(e,!0)},i.prototype.contain=function(){var t=this.viewport.getViewBox(),e=Math.max(this.width/t.width,this.height/t.height);this.zoom(e,!0)},i.prototype.center=function(){var t=this.viewport.getViewBox(),e=.5*(this.width-(t.width+2*t.x)*this.getZoom()),o=.5*(this.height-(t.height+2*t.y)*this.getZoom());this.getPublicInstance().pan({x:e,y:o})},i.prototype.updateBBox=function(){this.viewport.simpleViewBoxCache()},i.prototype.pan=function(t){var e=this.viewport.getCTM();e.e=t.x,e.f=t.y,this.viewport.setCTM(e)},i.prototype.panBy=function(t){var e=this.viewport.getCTM();e.e+=t.x,e.f+=t.y,this.viewport.setCTM(e)},i.prototype.getPan=function(){var t=this.viewport.getState();return{x:t.x,y:t.y}},i.prototype.resize=function(){var t=a.getBoundingClientRectNormalized(this.svg);this.width=t.width,this.height=t.height;var e=this.viewport;e.options.width=this.width,e.options.height=this.height,e.processCTM(),this.options.controlIconsEnabled&&(this.getPublicInstance().disableControlIcons(),this.getPublicInstance().enableControlIcons())},i.prototype.destroy=function(){var e=this;for(var t in this.beforeZoom=null,this.onZoom=null,this.beforePan=null,this.onPan=null,(this.onUpdatedCTM=null)!=this.options.customEventsHandler&&this.options.customEventsHandler.destroy({svgElement:this.svg,eventsListenerElement:this.options.eventsListenerElement,instance:this.getPublicInstance()}),this.eventListeners)(this.options.eventsListenerElement||this.svg).removeEventListener(t,this.eventListeners[t],!this.options.preventMouseEventsDefault&&h);this.disableMouseWheelZoom(),this.getPublicInstance().disableControlIcons(),this.reset(),c=c.filter(function(t){return t.svg!==e.svg}),delete this.options,delete this.viewport,delete this.publicInstance,delete this.pi,this.getPublicInstance=function(){return null}},i.prototype.getPublicInstance=function(){var o=this;return this.publicInstance||(this.publicInstance=this.pi={enablePan:function(){return o.options.panEnabled=!0,o.pi},disablePan:function(){return o.options.panEnabled=!1,o.pi},isPanEnabled:function(){return!!o.options.panEnabled},pan:function(t){return o.pan(t),o.pi},panBy:function(t){return o.panBy(t),o.pi},getPan:function(){return o.getPan()},setBeforePan:function(t){return o.options.beforePan=null===t?null:r.proxy(t,o.publicInstance),o.pi},setOnPan:function(t){return o.options.onPan=null===t?null:r.proxy(t,o.publicInstance),o.pi},enableZoom:function(){return o.options.zoomEnabled=!0,o.pi},disableZoom:function(){return o.options.zoomEnabled=!1,o.pi},isZoomEnabled:function(){return!!o.options.zoomEnabled},enableControlIcons:function(){return o.options.controlIconsEnabled||(o.options.controlIconsEnabled=!0,s.enable(o)),o.pi},disableControlIcons:function(){return o.options.controlIconsEnabled&&(o.options.controlIconsEnabled=!1,s.disable(o)),o.pi},isControlIconsEnabled:function(){return!!o.options.controlIconsEnabled},enableDblClickZoom:function(){return o.options.dblClickZoomEnabled=!0,o.pi},disableDblClickZoom:function(){return o.options.dblClickZoomEnabled=!1,o.pi},isDblClickZoomEnabled:function(){return!!o.options.dblClickZoomEnabled},enableMouseWheelZoom:function(){return o.enableMouseWheelZoom(),o.pi},disableMouseWheelZoom:function(){return o.disableMouseWheelZoom(),o.pi},isMouseWheelZoomEnabled:function(){return!!o.options.mouseWheelZoomEnabled},setZoomScaleSensitivity:function(t){return o.options.zoomScaleSensitivity=t,o.pi},setMinZoom:function(t){return o.options.minZoom=t,o.pi},setMaxZoom:function(t){return o.options.maxZoom=t,o.pi},setBeforeZoom:function(t){return o.options.beforeZoom=null===t?null:r.proxy(t,o.publicInstance),o.pi},setOnZoom:function(t){return o.options.onZoom=null===t?null:r.proxy(t,o.publicInstance),o.pi},zoom:function(t){return o.publicZoom(t,!0),o.pi},zoomBy:function(t){return o.publicZoom(t,!1),o.pi},zoomAtPoint:function(t,e){return o.publicZoomAtPoint(t,e,!0),o.pi},zoomAtPointBy:function(t,e){return o.publicZoomAtPoint(t,e,!1),o.pi},zoomIn:function(){return this.zoomBy(1+o.options.zoomScaleSensitivity),o.pi},zoomOut:function(){return this.zoomBy(1/(1+o.options.zoomScaleSensitivity)),o.pi},getZoom:function(){return o.getRelativeZoom()},setOnUpdatedCTM:function(t){return o.options.onUpdatedCTM=null===t?null:r.proxy(t,o.publicInstance),o.pi},resetZoom:function(){return o.resetZoom(),o.pi},resetPan:function(){return o.resetPan(),o.pi},reset:function(){return o.reset(),o.pi},fit:function(){return o.fit(),o.pi},contain:function(){return o.contain(),o.pi},center:function(){return o.center(),o.pi},updateBBox:function(){return o.updateBBox(),o.pi},resize:function(){return o.resize(),o.pi},getSizes:function(){return{width:o.width,height:o.height,realZoom:o.getZoom(),viewBox:o.viewport.getViewBox()}},destroy:function(){return o.destroy(),o.pi}}),this.publicInstance};var c=[];e.exports=function(t,e){var o=r.getSvg(t);if(null===o)return null;for(var n=c.length-1;0<=n;n--)if(c[n].svg===o)return c[n].instance.getPublicInstance();return c.push({svg:o,instance:new i(o,e)}),c[c.length-1].instance.getPublicInstance()}},{"./control-icons":1,"./shadow-viewport":2,"./svg-utilities":5,"./uniwheel":6,"./utilities":7}],5:[function(t,e,o){var l=t("./utilities"),s="unknown";document.documentMode&&(s="ie"),e.exports={svgNS:"http://www.w3.org/2000/svg",xmlNS:"http://www.w3.org/XML/1998/namespace",xmlnsNS:"http://www.w3.org/2000/xmlns/",xlinkNS:"http://www.w3.org/1999/xlink",evNS:"http://www.w3.org/2001/xml-events",getBoundingClientRectNormalized:function(t){if(t.clientWidth&&t.clientHeight)return{width:t.clientWidth,height:t.clientHeight};if(t.getBoundingClientRect())return t.getBoundingClientRect();throw new Error("Cannot get BoundingClientRect for SVG.")},getOrCreateViewport:function(t,e){var o=null;if(!(o=l.isElement(e)?e:t.querySelector(e))){var n=Array.prototype.slice.call(t.childNodes||t.children).filter(function(t){return"defs"!==t.nodeName&&"#text"!==t.nodeName});1===n.length&&"g"===n[0].nodeName&&null===n[0].getAttribute("transform")&&(o=n[0])}if(!o){var i="viewport-"+(new Date).toISOString().replace(/\D/g,"");(o=document.createElementNS(this.svgNS,"g")).setAttribute("id",i);var s=t.childNodes||t.children;if(s&&0<s.length)for(var r=s.length;0<r;r--)"defs"!==s[s.length-r].nodeName&&o.appendChild(s[s.length-r]);t.appendChild(o)}var a=[];return o.getAttribute("class")&&(a=o.getAttribute("class").split(" ")),~a.indexOf("svg-pan-zoom_viewport")||(a.push("svg-pan-zoom_viewport"),o.setAttribute("class",a.join(" "))),o},setupSvgAttributes:function(t){if(t.setAttribute("xmlns",this.svgNS),t.setAttributeNS(this.xmlnsNS,"xmlns:xlink",this.xlinkNS),t.setAttributeNS(this.xmlnsNS,"xmlns:ev",this.evNS),null!==t.parentNode){var e=t.getAttribute("style")||"";-1===e.toLowerCase().indexOf("overflow")&&t.setAttribute("style","overflow: hidden; "+e)}},internetExplorerRedisplayInterval:300,refreshDefsGlobal:l.throttle(function(){for(var t=document.querySelectorAll("defs"),e=t.length,o=0;o<e;o++){var n=t[o];n.parentNode.insertBefore(n,n)}},this?this.internetExplorerRedisplayInterval:null),setCTM:function(t,e,o){var n=this,i="matrix("+e.a+","+e.b+","+e.c+","+e.d+","+e.e+","+e.f+")";t.setAttributeNS(null,"transform",i),"transform"in t.style?t.style.transform=i:"-ms-transform"in t.style?t.style["-ms-transform"]=i:"-webkit-transform"in t.style&&(t.style["-webkit-transform"]=i),"ie"===s&&o&&(o.parentNode.insertBefore(o,o),window.setTimeout(function(){n.refreshDefsGlobal()},n.internetExplorerRedisplayInterval))},getEventPoint:function(t,e){var o=e.createSVGPoint();return l.mouseAndTouchNormalize(t,e),o.x=t.clientX,o.y=t.clientY,o},getSvgCenterPoint:function(t,e,o){return this.createSVGPoint(t,e/2,o/2)},createSVGPoint:function(t,e,o){var n=t.createSVGPoint();return n.x=e,n.y=o,n}}},{"./utilities":7}],6:[function(t,e,o){function s(t,o){function e(t){var e={originalEvent:t=t||window.event,target:t.target||t.srcElement,type:"wheel",deltaMode:"MozMousePixelScroll"==t.type?0:1,deltaX:0,delatZ:0,preventDefault:function(){t.preventDefault?t.preventDefault():t.returnValue=!1}};return"mousewheel"==l?(e.deltaY=-.025*t.wheelDelta,t.wheelDeltaX&&(e.deltaX=-.025*t.wheelDeltaX)):e.deltaY=t.detail,o(e)}return h.push({element:t,fn:e}),e}function n(t,e,o,n){var i;i="wheel"===l?o:s(t,o),t[r](u+e,i,n?c:p)}function i(t,e,o,n){var i;i="wheel"===l?o:function(t){for(var e=0;e<h.length;e++)if(h[e].element===t)return h[e].fn;return function(){}}(t),t[a](u+e,i,n?c:p),function(t){for(var e=0;e<h.length;e++)if(h[e].element===t)return h.splice(e,1)}(t)}var r,a,l,u,h,c,p;e.exports=(h=[],p={passive:!(c={passive:!(u="")})},window.addEventListener?(r="addEventListener",a="removeEventListener"):(r="attachEvent",a="detachEvent",u="on"),l="onwheel"in document.createElement("div")?"wheel":void 0!==document.onmousewheel?"mousewheel":"DOMMouseScroll",{on:function(t,e,o){n(t,l,e,o),"DOMMouseScroll"==l&&n(t,"MozMousePixelScroll",e,o)},off:function(t,e,o){i(t,l,e,o),"DOMMouseScroll"==l&&i(t,"MozMousePixelScroll",e,o)}})},{}],7:[function(t,e,o){function n(e){return function(t){window.setTimeout(t,e)}}e.exports={extend:function(t,e){for(var o in t=t||{},e)this.isObject(e[o])?t[o]=this.extend(t[o],e[o]):t[o]=e[o];return t},isElement:function(t){return t instanceof HTMLElement||t instanceof SVGElement||t instanceof SVGSVGElement||t&&"object"==typeof t&&null!==t&&1===t.nodeType&&"string"==typeof t.nodeName},isObject:function(t){return"[object Object]"===Object.prototype.toString.call(t)},isNumber:function(t){return!isNaN(parseFloat(t))&&isFinite(t)},getSvg:function(t){var e,o;if(this.isElement(t))e=t;else{if(!("string"==typeof t||t instanceof String))throw new Error("Provided selector is not an HTML object nor String");if(!(e=document.querySelector(t)))throw new Error("Provided selector did not find any elements. Selector: "+t)}if("svg"===e.tagName.toLowerCase())o=e;else if("object"===e.tagName.toLowerCase())o=e.contentDocument.documentElement;else{if("embed"!==e.tagName.toLowerCase())throw"img"===e.tagName.toLowerCase()?new Error('Cannot script an SVG in an "img" element. Please use an "object" element or an in-line SVG.'):new Error("Cannot get SVG.");o=e.getSVGDocument().documentElement}return o},proxy:function(t,e){return function(){return t.apply(e,arguments)}},getType:function(t){return Object.prototype.toString.apply(t).replace(/^\[object\s/,"").replace(/\]$/,"")},mouseAndTouchNormalize:function(t,e){if(void 0===t.clientX||null===t.clientX)if(t.clientX=0,void(t.clientY=0)!==t.touches&&t.touches.length){if(void 0!==t.touches[0].clientX)t.clientX=t.touches[0].clientX,t.clientY=t.touches[0].clientY;else if(void 0!==t.touches[0].pageX){var o=e.getBoundingClientRect();t.clientX=t.touches[0].pageX-o.left,t.clientY=t.touches[0].pageY-o.top}}else void 0!==t.originalEvent&&void 0!==t.originalEvent.clientX&&(t.clientX=t.originalEvent.clientX,t.clientY=t.originalEvent.clientY)},isDblClick:function(t,e){if(2===t.detail)return!0;if(null==e)return!1;var o=t.timeStamp-e.timeStamp,n=Math.sqrt(Math.pow(t.clientX-e.clientX,2)+Math.pow(t.clientY-e.clientY,2));return o<250&&n<10},now:Date.now||function(){return(new Date).getTime()},throttle:function(o,n,i){var s,r,a,l=this,u=null,h=0;i=i||{};function c(){h=!1===i.leading?0:l.now(),u=null,a=o.apply(s,r),u||(s=r=null)}return function(){var t=l.now();h||!1!==i.leading||(h=t);var e=n-(t-h);return s=this,r=arguments,e<=0||n<e?(clearTimeout(u),u=null,h=t,a=o.apply(s,r),u||(s=r=null)):u||!1===i.trailing||(u=setTimeout(c,e)),a}},createRequestAnimationFrame:function(t){var e=null;return"auto"!==t&&t<60&&1<t&&(e=Math.floor(1e3/t)),null===e?window.requestAnimationFrame||n(33):n(e)}}},{}]},{},[3]);