mockaton 11.4.0 → 12.0.0

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
@@ -1,13 +1,14 @@
1
- <img src="src/client/logo.svg" alt="Mockaton Logo" width="210" style="margin-top: 30px"/>
1
+ # Mockaton
2
+
3
+ An HTTP mock server for simulating APIs with minimal setup &mdash; ideal
4
+ for testing difficult to reproduce backend states.
2
5
 
3
6
  ![NPM Version](https://img.shields.io/npm/v/mockaton)
4
7
  [![Test](https://github.com/ericfortis/mockaton/actions/workflows/test.yml/badge.svg)](https://github.com/ericfortis/mockaton/actions/workflows/test.yml)
5
8
  [![codecov](https://codecov.io/github/ericfortis/mockaton/graph/badge.svg?token=90NYLMMG1J)](https://codecov.io/github/ericfortis/mockaton)
6
9
 
7
- An HTTP mock server for simulating APIs with minimal setup &mdash; ideal
8
- for testing difficult to reproduce backend states.
9
10
 
10
- ## [mockaton.com ↗](https://mockaton.com)
11
+ ## [Documentation ↗](https://mockaton.com)
11
12
  ## [Changelog ↗](https://mockaton.com/changelog)
12
13
 
13
14
  ## Overview
@@ -23,6 +24,25 @@ For example, for [/api/company/123](#), the filename could be:
23
24
 
24
25
  <br/>
25
26
 
27
+ ## Dashboard
28
+
29
+ <picture>
30
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/ericfortis/mockaton/refs/heads/main/pixaton-tests/tests/macos/pic-for-readme.vp832x740.light.gold.png">
31
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/ericfortis/mockaton/refs/heads/main/pixaton-tests/tests/macos/pic-for-readme.vp832x740.dark.gold.png">
32
+ <img alt="Mockaton Dashboard" src="https://raw.githubusercontent.com/ericfortis/mockaton/refs/heads/main/pixaton-tests/tests/macos/pic-for-readme.vp832x740.dark.gold.png">
33
+ </picture>
34
+
35
+ On the dashboard you can:
36
+ - Select a mock variant for a particular route
37
+ - 🕓 Delay responses
38
+ - Trigger an autogenerated `500` error
39
+ - …and cycle it off (for testing retries)
40
+
41
+ Nonetheless, there’s a programmatic API, which is handy for
42
+ setting up tests (see **Commander&nbsp;API** section below).
43
+
44
+ <br/>
45
+
26
46
 
27
47
  ## Quick Start (Docker)
28
48
  This will spin up Mockaton with the sample directories
@@ -44,26 +64,6 @@ curl localhost:2020/api/user
44
64
  ```
45
65
 
46
66
 
47
- <br/>
48
-
49
- ## Dashboard
50
-
51
-
52
- <picture>
53
- <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/ericfortis/mockaton/refs/heads/main/pixaton-tests/tests/macos/pic-for-readme.vp822x740.light.gold.png">
54
- <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/ericfortis/mockaton/refs/heads/main/pixaton-tests/tests/macos/pic-for-readme.vp822x740.dark.gold.png">
55
- <img alt="Mockaton Dashboard" src="https://raw.githubusercontent.com/ericfortis/mockaton/refs/heads/main/pixaton-tests/tests/macos/pic-for-readme.vp822x740.dark.gold.png">
56
- </picture>
57
-
58
- On the dashboard you can:
59
- - Select a mock variant for a particular route
60
- - 🕓 Delay responses
61
- - Trigger an autogenerated `500` error
62
- - …and cycle it off (for testing retries)
63
-
64
- Nonetheless, there’s a programmatic API, which is handy for
65
- setting up tests (see **Commander&nbsp;API** section below).
66
-
67
67
 
68
68
  ## License
69
69
  MIT
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "mockaton",
3
3
  "description": "HTTP Mock Server",
4
4
  "type": "module",
5
- "version": "11.4.0",
5
+ "version": "12.0.0",
6
6
  "exports": {
7
7
  ".": {
8
8
  "import": "./index.js",
package/src/client/app.js CHANGED
@@ -1,65 +1,15 @@
1
1
  import {
2
2
  createElement as r,
3
3
  createSvgElement as s,
4
- className, restoreFocus, Defer, Fragment
4
+ className, restoreFocus, Defer, Fragment, adoptCSS
5
5
  } from './dom-utils.js'
6
6
 
7
7
  import { store } from './app-store.js'
8
8
  import { parseFilename } from './Filename.js'
9
9
  import { HEADER_502 } from './ApiConstants.js'
10
10
 
11
-
12
- const CSS = {
13
- BulkSelector: null,
14
- CookieSelector: null,
15
- DelayToggler: null,
16
- ErrorToast: null,
17
- FallbackBackend: null,
18
- Field: null,
19
- GlobalDelayField: null,
20
- GlobalDelayJitterField: null,
21
- GlobalDelayWrap: null,
22
- GroupByMethod: null,
23
- InternalServerErrorToggler: null,
24
- Logo: null,
25
- MenuTrigger: null,
26
- Method: null,
27
- MockSelector: null,
28
- NotFoundToggler: null,
29
- PayloadViewer: null,
30
- PreviewLink: null,
31
- ProgressBar: null,
32
- ProxyToggler: null,
33
- ResetButton: null,
34
- Resizer: null,
35
- SaveProxiedCheckbox: null,
36
- SettingsMenu: null,
37
- Table: null,
38
- TableHeading: null,
39
- TableRow: null,
40
-
41
- animIn: null,
42
- canProxy: null,
43
- checkboxBody: null,
44
- chosen: null,
45
- dittoDir: null,
46
- leftSide: null,
47
- nonDefault: null,
48
- nonGroupedByMethod: null,
49
- rightSide: null,
50
- status4xx: null,
51
-
52
- syntaxAttr: null,
53
- syntaxAttrVal: null,
54
- syntaxKey: null,
55
- syntaxPunc: null,
56
- syntaxStr: null,
57
- syntaxTag: null,
58
- syntaxVal: null
59
- }
60
- for (const k of Object.keys(CSS))
61
- CSS[k] = k
62
-
11
+ import CSS from './styles.css' with { type: 'css' }
12
+ adoptCSS(CSS)
63
13
 
64
14
  const FocusGroup = {
65
15
  ProxyToggler: 0,
@@ -113,12 +63,7 @@ function Header() {
113
63
  className: CSS.Logo,
114
64
  href: 'https://mockaton.com'
115
65
  },
116
- r('object', {
117
- data: 'logo.svg',
118
- type: 'image/svg+xml',
119
- width: 120,
120
- height: 22
121
- })),
66
+ Logo()),
122
67
  r('div', null,
123
68
  r('div', className(CSS.GlobalDelayWrap),
124
69
  GlobalDelayField(),
@@ -763,7 +708,15 @@ ErrorToast.close = () => {
763
708
  }
764
709
 
765
710
 
766
- /** # Icons */
711
+ /** # Graphics */
712
+
713
+ function Logo() {
714
+ return (
715
+ s('svg', { viewBox: '0 0 556 100' },
716
+ s('path', { d: 'm13.75 1.8789c-5.9487 0.19352-10.865 4.5652-11.082 11.686v81.445c-1e-7 2.216 1.784 4 4 4h4.793c2.216 0 4-1.784 4-4v-64.982c0.02794-3.4488 3.0988-3.5551 4.2031-1.1562l16.615 59.059c1.4393 5.3711 5.1083 7.9633 8.7656 7.9473 3.6573 0.01603 7.3263-2.5762 8.7656-7.9473l16.615-59.059c1.1043-2.3989 4.1752-2.2925 4.2031 1.1562v64.982c0 2.216 1.784 4 4 4h4.793c2.216 0 4-1.784 4-4v-81.445c-0.17732-7.0807-5.1334-11.492-11.082-11.686-5.9487-0.19352-12.652 3.8309-15.609 13.619l-15.686 57.334-15.686-57.334c-2.9569-9.7882-9.6607-13.813-15.609-13.619zm239.19 0.074219c-2.216 0-4 1.784-4 4v89.057c0 2.216 1.784 4 4 4h4.793c2.216 0 3.9868-1.784 4-4l0.10644-17.94c0.0734-0.07237 12.175-13.75 12.175-13.75 5.6772 11.091 11.404 22.158 17.113 33.232 1.0168 1.9689 3.4217 2.7356 5.3906 1.7188l4.2578-2.1992c1.9689-1.0168 2.7356-3.4217 1.7188-5.3906-6.4691-12.585-12.958-25.16-19.442-37.738l17.223-19.771c1.4555-1.671 1.2803-4.189-0.39062-5.6445l-3.6133-3.1465c-0.73105-0.63679-1.6224-0.96212-2.5176-0.98633-1.151-0.03113-2.3063 0.43508-3.125 1.375l-28.896 33.174v-51.99c0-2.216-1.784-4-4-4zm-58.255 23.316c-10.699 0-19.312 8.6137-19.312 19.312v34.535c0 10.699 8.6137 19.312 19.312 19.312h19.717c10.699 0 19.311-8.6137 19.311-19.312l-0.125-7.8457c0-2.216-1.784-4-4-4h-4.6524c-2.216 0-4 1.784-4 4l3e-3 6.7888c3e-3 3.8063-1.5601 9.3694-8.4716 9.3694h-15.846c-6.9115 0-8.4766-5.5631-8.4766-12.475v-26.209c0-6.9115 1.5651-12.477 8.4766-12.477h15.846c6.6937 0 8.3697 5.2207 8.4687 11.828v2.2207c0 2.216 1.784 4 4 4h4.6524c2.216 0 4-1.784 4-4l0.125-5.7363c0-10.699-8.6117-19.312-19.311-19.312zm-72.182 0c-10.699 0-19.312 8.6137-19.312 19.312v34.535c0 10.699 8.6137 19.312 19.312 19.312h19.717c10.699 0 19.311-8.6137 19.311-19.312v-34.535c0-10.699-8.6117-19.312-19.311-19.312zm1.9356 11h15.846c6.9115 0 8.4746 5.5651 8.4746 12.477v26.209c0 6.9115-1.5631 12.475-8.4746 12.475h-15.846c-6.9115 0-8.4766-5.5631-8.4766-12.475v-26.209c0-6.9115 1.5651-12.477 8.4766-12.477z' }),
717
+ s('path', { opacity: 0.75, d: 'm331.9 25.27c-10.699 0-19.312 8.6137-19.312 19.312v4.3682c0 2.216 1.784 4 4 4h4.7715c2.216 0 4-1.784 4-4v-0.20414c0-6.9115 1.5651-12.477 8.4766-12.477h15.846c6.9115 0 8.4746 5.5651 8.4746 12.477v7.0148h-28.059c-10.699 0-19.312 8.6117-19.312 19.311v4.0477c0 10.699 8.6137 19.313 19.312 19.312h17.812c2.216-1e-6 4-1.784 4-4v-4.7715c0-2.216-1.784-4-4-4h-13.648c-6.9115-2e-5 -12.477-1.5651-12.477-8.5649 0-6.9998 5.5651-8.5629 12.477-8.5629h23.895v25.897c0 2.216 1.784 4 4 4h4.7715c2.216-1e-6 4-1.784 4-4v-49.848c0-10.699-8.6117-19.312-19.311-19.312z' }),
718
+ s('path', { d: 'm392.75 1.373c-2.216 0-4 1.784-4 4v18.043h-5.3086c-2.216 0-4 1.784-4 4v4.793c0 2.216 1.784 4 4 4h5.3086v51.398c0 6.1465 3.7064 10.823 9.232 10.823h16.531c2.216 0 4-1.784 4-4v-4.793c0-2.216-1.784-4-4-4h-12.97v-49.428h9.8711c2.216 0 4-1.784 4-4v-4.793c0-2.216-1.784-4-4-4h-9.8711v-18.043c0-2.216-1.784-4-4-4zm122.96 23.896c-10.699 0-19.312 8.6137-19.312 19.312v49.812c0 2.216 1.784 4 4 4h4.7715c2.216 0 4-1.784 4-4v-45.648c0-6.9115 1.5651-12.477 8.4766-12.477h15.846c6.9115 0 8.4746 5.5651 8.4746 12.477v45.684c0 2.216 1.784 4 4 4h4.7715c2.216-1e-6 4-1.784 4-4v-49.848c0-10.699-8.6117-19.312-19.311-19.312zm-69.999 0c-10.699 0-19.312 8.6137-19.312 19.312v34.535c0 10.699 8.6137 19.312 19.312 19.312h19.717c10.699 0 19.311-8.6137 19.311-19.312v-34.535c0-10.699-8.6117-19.312-19.311-19.312zm1.9356 11h15.846c6.9115 0 8.4746 5.5651 8.4746 12.477v26.209c0 6.9115-1.5631 12.475-8.4746 12.475h-15.846c-6.9115 0-8.4766-5.5631-8.4766-12.475v-26.209c0-6.9115 1.5651-12.477 8.4766-12.477z' })))
719
+ }
767
720
 
768
721
  function TimerIcon() {
769
722
  return (
@@ -965,7 +918,3 @@ function SyntaxXML(xml) {
965
918
  frag.normalize()
966
919
  return frag
967
920
  }
968
-
969
-
970
- /*
971
- */
@@ -0,0 +1,71 @@
1
+ import { test } from 'node:test'
2
+ import { deepEqual } from 'node:assert/strict'
3
+ import { extractClassNames } from './dom-utils.js'
4
+
5
+
6
+ const cssRules = [
7
+ { cssText: '.TopLevelPascal { color: red; }' },
8
+ { cssText: '.topLevelCamel { color: blue; }' },
9
+ { cssText: '.top_level_snake { color: green; }' },
10
+ { cssText: '.top-level-kebab { color: yellow; }' },
11
+ { cssText: '.Level2Parent {\n & .level2ChildCamel { color: purple; }\n}' },
12
+ { cssText: '.level2Base {\n &.level2ModifierCamel { font-weight: bold; }\n}' },
13
+ { cssText: '.Level3Parent {\n & .level3ChildCamel {\n & .level3_grand_child_snake { color: orange; }\n}\n}' },
14
+ { cssText: '.pseudoParent {\n &:hover { background: red; }\n & .pseudoNestedChild { color: pink; }\n}' },
15
+ { cssText: '.multiClass1, .multi_class_2 { padding: 10px; }' },
16
+ { cssText: '.combParent {\n & > .combChildDirect { margin: 5px; }\n}' },
17
+ { cssText: '.siblingBase {\n & + .siblingAdjacent { border: 1px solid; }\n}' },
18
+ { cssText: '@media (max-width: 768px) {\n .mediaQueryClass {\n & .mqNestedChild { display: none; }\n}\n}' },
19
+ { cssText: '.class_with_123_numbers { color: cyan; }' },
20
+ { cssText: '._privateStyleClass { opacity: 0.5; }' },
21
+ { cssText: '.stringTest { content: ".shouldNotBeExtracted"; background: url(".alsoIgnored"); }' },
22
+ { cssText: '.ComplexRoot {\n & .level2-kebab {\n &.level2ModCamel { color: red; }\n & .level3_snake {\n & .level4PascalChild { color: blue; }\n}\n}\n}' }
23
+ ]
24
+
25
+ const expected = {
26
+ TopLevelPascal: null,
27
+ topLevelCamel: null,
28
+ top_level_snake: null,
29
+ 'top-level-kebab': null,
30
+
31
+ Level2Parent: null,
32
+ level2ChildCamel: null,
33
+ level2Base: null,
34
+ level2ModifierCamel: null,
35
+
36
+ Level3Parent: null,
37
+ level3ChildCamel: null,
38
+ level3_grand_child_snake: null,
39
+
40
+ pseudoParent: null,
41
+ pseudoNestedChild: null,
42
+
43
+ multiClass1: null,
44
+ multi_class_2: null,
45
+
46
+ combParent: null,
47
+ combChildDirect: null,
48
+
49
+ siblingBase: null,
50
+ siblingAdjacent: null,
51
+
52
+ mediaQueryClass: null,
53
+ mqNestedChild: null,
54
+
55
+ class_with_123_numbers: null,
56
+ _privateStyleClass: null,
57
+
58
+ stringTest: null,
59
+
60
+ ComplexRoot: null,
61
+ 'level2-kebab': null,
62
+ level2ModCamel: null,
63
+ level3_snake: null,
64
+ level4PascalChild: null
65
+ }
66
+ for (const k of Object.keys(expected))
67
+ expected[k] = k
68
+
69
+
70
+ test('extracts', () => deepEqual(extractClassNames({ cssRules }), expected))
71
+
@@ -78,3 +78,28 @@ function selectorFor(elem) {
78
78
  return path.reverse().join('>')
79
79
  }
80
80
 
81
+
82
+
83
+ // Minimal implementation of CSS Modules in the browser
84
+ // TODO think about avoiding clashes when using multiple files. e.g.:
85
+ // - should the user pass a prefix?, or
86
+ // - should the ensure there's a unique top-level classname on each file
87
+ // TODO ignore rules in comments?
88
+
89
+ export function adoptCSS(sheet) {
90
+ document.adoptedStyleSheets.push(sheet)
91
+ Object.assign(sheet, extractClassNames(sheet))
92
+ }
93
+
94
+ export function extractClassNames({ cssRules }) {
95
+ // Class names must begin with _ or a letter, then it can have numbers and hyphens
96
+ const reClassName = /(?:^|[\s,{>])&?\s*\.([a-zA-Z_][\w-]*)/g
97
+
98
+ const cNames = {}
99
+ let match
100
+ for (const rule of cssRules)
101
+ while (match = reClassName.exec(rule.cssText))
102
+ cNames[match[1]] = match[1]
103
+ return cNames
104
+ }
105
+
@@ -14,19 +14,10 @@ export const IndexHtml = hotReloadEnabled => `
14
14
  <head>
15
15
  <meta charset="UTF-8">
16
16
  <base href="${API.dashboard}/">
17
-
18
- <link rel="stylesheet" href="styles.css">
17
+
19
18
  <script type="module" src="app.js"></script>
20
-
21
19
  <link rel="preload" href="${API.state}" as="fetch" crossorigin>
22
20
 
23
- <link rel="modulepreload" href="ApiConstants.js">
24
- <link rel="modulepreload" href="ApiCommander.js">
25
- <link rel="modulepreload" href="Filename.js">
26
- <link rel="modulepreload" href="app-store.js">
27
- <link rel="modulepreload" href="dom-utils.js">
28
- <link rel="preload" href="logo.svg" as="image">
29
-
30
21
  <link rel="icon" href="data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m235 33.7v202c0 9.19-5.81 14-17.4 14-11.6 0-17.4-4.83-17.4-14v-151c-0.115-4.49-6.72-5.88-8.46-0.87l-48.3 155c-2.22 7.01-7.72 10.1-16 9.9-3.63-0.191-7.01-1.14-9.66-2.89-2.89-1.72-4.83-4.34-5.57-7.72-11.1-37-22.6-74.3-34.1-111-4.34-14-8.95-31.4-14-48.3-1.82-4.83-8.16-5.32-8.46 1.16v156c0 9.19-5.81 14-17.4 14-11.6 0-17.4-4.83-17.4-14v-207c0-5.74 2.62-13.2 9.39-16.3 7.5-3.14 15-4.05 21.8-3.8 3.14 0 6.03 0.686 8.95 1.46 3.14 0.797 6.03 1.98 8.7 3.63 2.65 1.38 5.32 3.14 7.5 5.57 2.22 2.22 3.87 4.83 5.07 7.72l45.8 157c4.63-15.9 32.4-117 33.3-121 4.12-13.8 7.72-26.5 10.9-38.7 1.16-2.65 2.89-5.32 5.07-7.5 2.15-2.15 4.58-4.12 7.5-5.32 2.65-1.57 5.57-2.89 8.46-3.63 3.14-0.797 9.44-0.988 12.1-0.988 11.6 1.07 29.4 9.14 29.4 27z' fill='%23808080'/%3E%3C/svg%3E">
31
22
  <meta name="viewport" content="width=device-width, initial-scale=1">
32
23
  <meta name="description" content="HTTP Mock Server">
@@ -138,8 +138,10 @@ header {
138
138
  margin-right: 22px;
139
139
  margin-bottom: 3px;
140
140
 
141
- object {
141
+ svg {
142
+ width: 120px;
142
143
  pointer-events: none;
144
+ fill: var(--colorText);
143
145
  }
144
146
  }
145
147
 
@@ -151,22 +153,14 @@ header {
151
153
  gap: 16px 8px;
152
154
  }
153
155
 
154
- @media (max-width: 820px) {
156
+ @media (max-width: 830px) {
155
157
  .Logo {
156
- margin-top: 16px;
157
- align-self: start;
158
- }
159
-
160
- > div {
161
- width: 400px;
162
- .MenuTrigger {
163
- margin-left: unset;
164
- }
158
+ display: none;
165
159
  }
166
160
  }
167
- @media (max-width: 424px) {
168
- > img {
169
- display: none;
161
+ @media (max-width: 690px) {
162
+ > div .MenuTrigger {
163
+ margin-left: unset;
170
164
  }
171
165
  }
172
166
 
@@ -222,16 +216,16 @@ header {
222
216
  stroke-width: 3px;
223
217
  border-radius: 50%;
224
218
  }
225
-
219
+
226
220
  &:focus-within {
227
221
  z-index: 100;
228
222
  }
229
223
  }
230
-
224
+
231
225
  &.GlobalDelayJitterField {
232
- width: 70px;
226
+ width: 80px;
233
227
  span {
234
- margin-left: 0;
228
+ margin-left: 4px;
235
229
  }
236
230
  input {
237
231
  border-left: 2px solid transparent;
@@ -10,7 +10,7 @@ async function longPollDevChanges() {
10
10
 
11
11
  const file = await response.json() || ''
12
12
  if (file.endsWith('.css')) {
13
- hotReloadCSS(file)
13
+ await hotReloadCSS(file)
14
14
  longPollDevChanges()
15
15
  }
16
16
  else if (file)
@@ -24,10 +24,7 @@ async function longPollDevChanges() {
24
24
  }
25
25
  }
26
26
 
27
- function hotReloadCSS(file) {
28
- const link = document.querySelector(`link[href*="${file}"]`)
29
- if (link) {
30
- const [url] = link.href.split('?')
31
- link.href = url + '?' + Date.now()
32
- }
27
+ async function hotReloadCSS(file) {
28
+ const mod = await import(`./${file}?${Date.now()}`, { with: { type: 'css' } })
29
+ document.adoptedStyleSheets = [mod.default]
33
30
  }
@@ -1,18 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <svg width="556" height="100" version="1.1" viewBox="0 0 556 100" xmlns="http://www.w3.org/2000/svg">
3
- <style>
4
- @media (prefers-color-scheme: light) { :root { --color: #333 } }
5
- @media (prefers-color-scheme: dark) { :root { --color: #eee } }
6
- path {
7
- fill: #777;
8
- fill: var(--color);
9
- }
10
- </style>
11
- <path
12
- d="m13.75 1.8789c-5.9487 0.19352-10.865 4.5652-11.082 11.686v81.445c-1e-7 2.216 1.784 4 4 4h4.793c2.216 0 4-1.784 4-4v-64.982c0.02794-3.4488 3.0988-3.5551 4.2031-1.1562l16.615 59.059c1.4393 5.3711 5.1083 7.9633 8.7656 7.9473 3.6573 0.01603 7.3263-2.5762 8.7656-7.9473l16.615-59.059c1.1043-2.3989 4.1752-2.2925 4.2031 1.1562v64.982c0 2.216 1.784 4 4 4h4.793c2.216 0 4-1.784 4-4v-81.445c-0.17732-7.0807-5.1334-11.492-11.082-11.686-5.9487-0.19352-12.652 3.8309-15.609 13.619l-15.686 57.334-15.686-57.334c-2.9569-9.7882-9.6607-13.813-15.609-13.619zm239.19 0.074219c-2.216 0-4 1.784-4 4v89.057c0 2.216 1.784 4 4 4h4.793c2.216 0 3.9868-1.784 4-4l0.10644-17.94c0.0734-0.07237 12.175-13.75 12.175-13.75 5.6772 11.091 11.404 22.158 17.113 33.232 1.0168 1.9689 3.4217 2.7356 5.3906 1.7188l4.2578-2.1992c1.9689-1.0168 2.7356-3.4217 1.7188-5.3906-6.4691-12.585-12.958-25.16-19.442-37.738l17.223-19.771c1.4555-1.671 1.2803-4.189-0.39062-5.6445l-3.6133-3.1465c-0.73105-0.63679-1.6224-0.96212-2.5176-0.98633-1.151-0.03113-2.3063 0.43508-3.125 1.375l-28.896 33.174v-51.99c0-2.216-1.784-4-4-4zm-58.255 23.316c-10.699 0-19.312 8.6137-19.312 19.312v34.535c0 10.699 8.6137 19.312 19.312 19.312h19.717c10.699 0 19.311-8.6137 19.311-19.312l-0.125-7.8457c0-2.216-1.784-4-4-4h-4.6524c-2.216 0-4 1.784-4 4l3e-3 6.7888c3e-3 3.8063-1.5601 9.3694-8.4716 9.3694h-15.846c-6.9115 0-8.4766-5.5631-8.4766-12.475v-26.209c0-6.9115 1.5651-12.477 8.4766-12.477h15.846c6.6937 0 8.3697 5.2207 8.4687 11.828v2.2207c0 2.216 1.784 4 4 4h4.6524c2.216 0 4-1.784 4-4l0.125-5.7363c0-10.699-8.6117-19.312-19.311-19.312zm-72.182 0c-10.699 0-19.312 8.6137-19.312 19.312v34.535c0 10.699 8.6137 19.312 19.312 19.312h19.717c10.699 0 19.311-8.6137 19.311-19.312v-34.535c0-10.699-8.6117-19.312-19.311-19.312zm1.9356 11h15.846c6.9115 0 8.4746 5.5651 8.4746 12.477v26.209c0 6.9115-1.5631 12.475-8.4746 12.475h-15.846c-6.9115 0-8.4766-5.5631-8.4766-12.475v-26.209c0-6.9115 1.5651-12.477 8.4766-12.477z"/>
13
- <path
14
- d="m331.9 25.27c-10.699 0-19.312 8.6137-19.312 19.312v4.3682c0 2.216 1.784 4 4 4h4.7715c2.216 0 4-1.784 4-4v-0.20414c0-6.9115 1.5651-12.477 8.4766-12.477h15.846c6.9115 0 8.4746 5.5651 8.4746 12.477v7.0148h-28.059c-10.699 0-19.312 8.6117-19.312 19.311v4.0477c0 10.699 8.6137 19.313 19.312 19.312h17.812c2.216-1e-6 4-1.784 4-4v-4.7715c0-2.216-1.784-4-4-4h-13.648c-6.9115-2e-5 -12.477-1.5651-12.477-8.5649 0-6.9998 5.5651-8.5629 12.477-8.5629h23.895v25.897c0 2.216 1.784 4 4 4h4.7715c2.216-1e-6 4-1.784 4-4v-49.848c0-10.699-8.6117-19.312-19.311-19.312z"
15
- opacity="0.75"/>
16
- <path
17
- d="m392.75 1.373c-2.216 0-4 1.784-4 4v18.043h-5.3086c-2.216 0-4 1.784-4 4v4.793c0 2.216 1.784 4 4 4h5.3086v51.398c0 6.1465 3.7064 10.823 9.232 10.823h16.531c2.216 0 4-1.784 4-4v-4.793c0-2.216-1.784-4-4-4h-12.97v-49.428h9.8711c2.216 0 4-1.784 4-4v-4.793c0-2.216-1.784-4-4-4h-9.8711v-18.043c0-2.216-1.784-4-4-4zm122.96 23.896c-10.699 0-19.312 8.6137-19.312 19.312v49.812c0 2.216 1.784 4 4 4h4.7715c2.216 0 4-1.784 4-4v-45.648c0-6.9115 1.5651-12.477 8.4766-12.477h15.846c6.9115 0 8.4746 5.5651 8.4746 12.477v45.684c0 2.216 1.784 4 4 4h4.7715c2.216-1e-6 4-1.784 4-4v-49.848c0-10.699-8.6117-19.312-19.311-19.312zm-69.999 0c-10.699 0-19.312 8.6137-19.312 19.312v34.535c0 10.699 8.6137 19.312 19.312 19.312h19.717c10.699 0 19.311-8.6137 19.311-19.312v-34.535c0-10.699-8.6117-19.312-19.311-19.312zm1.9356 11h15.846c6.9115 0 8.4746 5.5651 8.4746 12.477v26.209c0 6.9115-1.5631 12.475-8.4746 12.475h-15.846c-6.9115 0-8.4766-5.5631-8.4766-12.475v-26.209c0-6.9115 1.5651-12.477 8.4766-12.477z"/>
18
- </svg>