@vizhub/runtime 0.0.1 → 0.0.3

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.
Files changed (120) hide show
  1. package/dist/assets/setupV3Runtime-BVr5lyKp.js +240 -0
  2. package/dist/computeSrcDoc.d.ts +13 -0
  3. package/dist/computeSrcDoc.d.ts.map +1 -0
  4. package/{src/index.ts → dist/index.d.ts} +1 -0
  5. package/dist/index.d.ts.map +1 -0
  6. package/{src/v2Runtime/bundle/rollup.browser.js → dist/index.js} +9286 -12810
  7. package/dist/useRuntime.d.ts +13 -0
  8. package/dist/useRuntime.d.ts.map +1 -0
  9. package/dist/v2Runtime/bundle/bubleJSXOnly.d.ts +5 -0
  10. package/dist/v2Runtime/bundle/bubleJSXOnly.d.ts.map +1 -0
  11. package/dist/v2Runtime/bundle/packageJson.d.ts +10 -0
  12. package/dist/v2Runtime/bundle/packageJson.d.ts.map +1 -0
  13. package/dist/v2Runtime/computeSrcDocV2.d.ts +3 -0
  14. package/dist/v2Runtime/computeSrcDocV2.d.ts.map +1 -0
  15. package/dist/v2Runtime/computeSrcDocV2.test.d.ts +2 -0
  16. package/dist/v2Runtime/computeSrcDocV2.test.d.ts.map +1 -0
  17. package/dist/v2Runtime/getComputedIndexHtml.d.ts +4 -0
  18. package/dist/v2Runtime/getComputedIndexHtml.d.ts.map +1 -0
  19. package/dist/v2Runtime/getComputedIndexHtml.test.d.ts +2 -0
  20. package/dist/v2Runtime/getComputedIndexHtml.test.d.ts.map +1 -0
  21. package/dist/v2Runtime/getText.d.ts +3 -0
  22. package/dist/v2Runtime/getText.d.ts.map +1 -0
  23. package/dist/v2Runtime/transformFiles.d.ts +3 -0
  24. package/dist/v2Runtime/transformFiles.d.ts.map +1 -0
  25. package/dist/v2Runtime/v3FilesToV2Files.d.ts +3 -0
  26. package/dist/v2Runtime/v3FilesToV2Files.d.ts.map +1 -0
  27. package/dist/v2Runtime/v3FilesToV2Files.test.d.ts +2 -0
  28. package/dist/v2Runtime/v3FilesToV2Files.test.d.ts.map +1 -0
  29. package/dist/v3Runtime/build.d.ts +14 -0
  30. package/dist/v3Runtime/build.d.ts.map +1 -0
  31. package/dist/v3Runtime/build.test.d.ts +2 -0
  32. package/dist/v3Runtime/build.test.d.ts.map +1 -0
  33. package/dist/v3Runtime/cleanRollupErrorMessage.d.ts +5 -0
  34. package/dist/v3Runtime/cleanRollupErrorMessage.d.ts.map +1 -0
  35. package/dist/v3Runtime/computeSrcDocV3.d.ts +7 -0
  36. package/dist/v3Runtime/computeSrcDocV3.d.ts.map +1 -0
  37. package/dist/v3Runtime/extractVizImport.d.ts +7 -0
  38. package/dist/v3Runtime/extractVizImport.d.ts.map +1 -0
  39. package/dist/v3Runtime/extractVizImport.test.d.ts +2 -0
  40. package/dist/v3Runtime/extractVizImport.test.d.ts.map +1 -0
  41. package/dist/v3Runtime/generateRollupErrorMessage.d.ts +5 -0
  42. package/dist/v3Runtime/generateRollupErrorMessage.d.ts.map +1 -0
  43. package/dist/v3Runtime/importFromViz.d.ts +1 -0
  44. package/dist/v3Runtime/importFromViz.d.ts.map +1 -0
  45. package/{src/v3Runtime/index.ts → dist/v3Runtime/index.d.ts} +1 -0
  46. package/dist/v3Runtime/index.d.ts.map +1 -0
  47. package/dist/v3Runtime/parseId.d.ts +7 -0
  48. package/dist/v3Runtime/parseId.d.ts.map +1 -0
  49. package/dist/v3Runtime/setupV3Runtime.d.ts +15 -0
  50. package/dist/v3Runtime/setupV3Runtime.d.ts.map +1 -0
  51. package/dist/v3Runtime/transformDSV/index.d.ts +3 -0
  52. package/dist/v3Runtime/transformDSV/index.d.ts.map +1 -0
  53. package/dist/v3Runtime/transformSvelte.d.ts +6 -0
  54. package/dist/v3Runtime/transformSvelte.d.ts.map +1 -0
  55. package/dist/v3Runtime/types.d.ts +65 -0
  56. package/dist/v3Runtime/types.d.ts.map +1 -0
  57. package/dist/v3Runtime/urlLoad.d.ts +1 -0
  58. package/dist/v3Runtime/urlLoad.d.ts.map +1 -0
  59. package/dist/v3Runtime/virtual.d.ts +1 -0
  60. package/dist/v3Runtime/virtual.d.ts.map +1 -0
  61. package/dist/v3Runtime/vizCache.d.ts +11 -0
  62. package/dist/v3Runtime/vizCache.d.ts.map +1 -0
  63. package/dist/v3Runtime/vizCache.test.d.ts +2 -0
  64. package/dist/v3Runtime/vizCache.test.d.ts.map +1 -0
  65. package/dist/v3Runtime/vizLoad.d.ts +8 -0
  66. package/dist/v3Runtime/vizLoad.d.ts.map +1 -0
  67. package/dist/v3Runtime/vizLoadSvelte.d.ts +1 -0
  68. package/dist/v3Runtime/vizLoadSvelte.d.ts.map +1 -0
  69. package/dist/v3Runtime/vizResolve.d.ts +10 -0
  70. package/dist/v3Runtime/vizResolve.d.ts.map +1 -0
  71. package/dist/v3Runtime/worker.d.ts +2 -0
  72. package/dist/v3Runtime/worker.d.ts.map +1 -0
  73. package/package.json +13 -6
  74. package/src/computeSrcDoc.ts +0 -68
  75. package/src/useRuntime.ts +0 -394
  76. package/src/v2Runtime/bundle/bubleJSXOnly.ts +0 -34
  77. package/src/v2Runtime/bundle/getLibraries.js +0 -31
  78. package/src/v2Runtime/bundle/hypothetical.js +0 -232
  79. package/src/v2Runtime/bundle/index.js +0 -88
  80. package/src/v2Runtime/bundle/packageJson.ts +0 -49
  81. package/src/v2Runtime/bundle.test.js +0 -151
  82. package/src/v2Runtime/computeSrcDocV2.test.ts +0 -163
  83. package/src/v2Runtime/computeSrcDocV2.ts +0 -34
  84. package/src/v2Runtime/getComputedIndexHtml.test.ts +0 -33
  85. package/src/v2Runtime/getComputedIndexHtml.ts +0 -106
  86. package/src/v2Runtime/getText.ts +0 -19
  87. package/src/v2Runtime/magicSandbox.js +0 -291
  88. package/src/v2Runtime/packageJson.js +0 -42
  89. package/src/v2Runtime/transformFiles.test.js +0 -18
  90. package/src/v2Runtime/transformFiles.ts +0 -15
  91. package/src/v2Runtime/v3FilesToV2Files.test.ts +0 -20
  92. package/src/v2Runtime/v3FilesToV2Files.ts +0 -14
  93. package/src/v3Runtime/build.test.ts +0 -474
  94. package/src/v3Runtime/build.ts +0 -270
  95. package/src/v3Runtime/cleanRollupErrorMessage.ts +0 -15
  96. package/src/v3Runtime/computeSrcDocV3.ts +0 -151
  97. package/src/v3Runtime/extractVizImport.test.ts +0 -41
  98. package/src/v3Runtime/extractVizImport.ts +0 -34
  99. package/src/v3Runtime/generateRollupErrorMessage.ts +0 -84
  100. package/src/v3Runtime/importFromViz.ts +0 -36
  101. package/src/v3Runtime/parseId.ts +0 -14
  102. package/src/v3Runtime/setupV3Runtime.ts +0 -478
  103. package/src/v3Runtime/transformDSV/d3-dsv-custom-build/bundle-modified-src.js +0 -121
  104. package/src/v3Runtime/transformDSV/d3-dsv-custom-build/bundle-modified.js +0 -121
  105. package/src/v3Runtime/transformDSV/d3-dsv-custom-build/bundle.js +0 -239
  106. package/src/v3Runtime/transformDSV/d3-dsv-custom-build/index.js +0 -1
  107. package/src/v3Runtime/transformDSV/d3-dsv-custom-build/package-lock.json +0 -475
  108. package/src/v3Runtime/transformDSV/d3-dsv-custom-build/package.json +0 -19
  109. package/src/v3Runtime/transformDSV/d3-dsv-custom-build/rollup.config.js +0 -9
  110. package/src/v3Runtime/transformDSV/index.ts +0 -71
  111. package/src/v3Runtime/transformSvelte.ts +0 -111
  112. package/src/v3Runtime/types.ts +0 -158
  113. package/src/v3Runtime/urlLoad.ts +0 -33
  114. package/src/v3Runtime/virtual.ts +0 -27
  115. package/src/v3Runtime/vizCache.test.ts +0 -126
  116. package/src/v3Runtime/vizCache.ts +0 -60
  117. package/src/v3Runtime/vizLoad.ts +0 -68
  118. package/src/v3Runtime/vizLoadSvelte.ts +0 -46
  119. package/src/v3Runtime/vizResolve.ts +0 -100
  120. package/src/v3Runtime/worker.ts +0 -231
@@ -1,291 +0,0 @@
1
- // This function was originally part of Blockbuider.
2
- // The original code can be found at https://github.com/enjalot/blockbuilder/blob/master/public/js/utils/parseCode.js
3
- // The original author is Ian Johnson (@enjalot).
4
- // Contributors include:
5
- // - Geoffery Miller (@georules)
6
- // - Paweł Kowalski (@pavelloz)
7
- // - Erik Hazzard (@erikhazzard)
8
- // - Curran Kelleher (@curran)
9
- // - Micah Stubbs (@micahstubbs)
10
-
11
- // This is from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
12
- function escapeRegExp(string) {
13
- return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
14
- }
15
-
16
- export default function (template, files) {
17
- // We parse the user's code to handle some cases where people expect
18
- // to be able to use relative urls to load files associated with the block
19
- // (things like external script files, style files or using XHR to grab data)
20
- // We use RegExps and override the XMLHttpRequest object inside the iframe.
21
- // obviously this could have some unintended side-effects,
22
- // but it is presumed that the scenarios where these would fail
23
- // fall far outside the customary use of blocks.
24
-
25
- // Lets replace relative URL that ignores protocol with http
26
- // this should work, but its probably an iframe problem
27
- // http://stackoverflow.com/questions/550038/is-it-valid-to-replace-http-with-in-a-script-src-http
28
- var find = '<link.*?href=["\']//.*?["\'].*?>';
29
- var re = new RegExp(find, 'g');
30
- var matches = template.match(re);
31
- if (matches) {
32
- matches.forEach(function (match, i) {
33
- var proto = match.replace('//', 'https://');
34
- template = template.replace(match, proto);
35
- });
36
- }
37
- find = '<script.*?src=["\']//.*?["\'].*?>';
38
- re = new RegExp(find, 'g');
39
- matches = template.match(re);
40
- if (matches) {
41
- matches.forEach(function (match, i) {
42
- var proto = match.replace('//', 'https://');
43
- template = template.replace(match, proto);
44
- });
45
- }
46
-
47
- var referencedFiles = {};
48
- var fileNames = Object.keys(files);
49
- fileNames.forEach(function (file) {
50
- if (!files[file] || !files[file].content) return;
51
- if (file === 'index.html') return;
52
- if (file === 'thumbnail.png') return; // lets ignore the thumbnail if its there
53
-
54
- if (file.indexOf('.js') > 0) {
55
- // We first try to find instances of loading js files through a <script> tag.
56
- // We can't fall back on the raw_url because you can't load scripts with MIME type text.
57
- // This does have the benefit of live reloading when changing a script file.
58
- var find =
59
- '<script.*?src=["\']' +
60
- escapeRegExp(file) +
61
- '["\'].*?>';
62
- var re = new RegExp(find, 'g');
63
- var matches = template.match(re);
64
- if (matches) {
65
- // if we found one, replace it with the code and return.
66
- template = template.replace(
67
- re,
68
- '<script>' + files[file].content,
69
- );
70
- // this won't work for code that has non-ascii characters in it... which is quite a lot of d3 code
71
- // template = template.replace(re, '<script src="data:text/javascript;base64,' + btoa(files[file].content) + '">')
72
- // this works with non-ascii characters but would take more acrobatics to support the defer keyword
73
- // and also seems like it would make debugging the inserted scripts more complicated
74
- // template = template.replace(re, '<script src="data:text/javascript;base64,' + b64EncodeUnicode(files[file].content) + '">')
75
- return;
76
- }
77
- }
78
- if (file.indexOf('.css') > 0) {
79
- // We support loading of css files with relative paths if they are included in the gist.
80
- // This has the added benefit of live reloading the iframe when editing the style
81
- find =
82
- '<link.*?href=["\']' +
83
- escapeRegExp(file) +
84
- '["\'].*?>';
85
- re = new RegExp(find, 'g');
86
- matches = template.match(re);
87
- if (matches) {
88
- // if we found one, replace it with the code and return.
89
- template = template.replace(
90
- re,
91
- '<style>' + files[file].content + '</style>',
92
- );
93
- return;
94
- }
95
- }
96
-
97
- // don't try to make html files loadable in this way
98
- // it has the chance of screwing up the rest of the actual file, and unlikely
99
- // someone wants to load an html file via ajax...
100
- if (file.indexOf('.html') >= 0) return;
101
-
102
- /*
103
- var find = "[\"\']" + file + "[\"\']"
104
- var re = new RegExp(find, 'g')
105
- template = template.replace(re, "'" + rawUrl + "'")
106
- */
107
- // we keep a list of all the files we might allow people to XHR request.
108
- // it would be possible to optimize by using the above commented out regex
109
- // but if a user programatically generates
110
- referencedFiles[file] = files[file].content;
111
- });
112
-
113
- // We need to have the file names and their contents available inside the iframe
114
- // if we want to be able to return them in our short-circuited XHR requests.
115
- var filesString = encodeURIComponent(
116
- JSON.stringify(referencedFiles),
117
- );
118
- var fileNamesString = JSON.stringify(
119
- Object.keys(referencedFiles),
120
- );
121
- template =
122
- '<meta charset="utf-8"><script>' +
123
- // 'var __files = ' + filesString + ';' +
124
- 'var __filesURI = "' +
125
- filesString +
126
- '";\n' +
127
- 'var __files = JSON.parse(decodeURIComponent(__filesURI));\n' +
128
- 'var __fileNames = ' +
129
- fileNamesString +
130
- ';' +
131
- '</script>' +
132
- template;
133
-
134
- // We override the XMLHttpRequest API in order to serve our local copies of files
135
- // without going to the server. This allows us to live-update the iframe as soon
136
- // as the file changes.
137
- // I was able to figure this out thanks to this page:
138
- // http://ajaxref.com/ch7/xhrhijackfullprototype.html
139
-
140
- var xmlOverride = `<script>(function() {
141
- var XHR = window.XMLHttpRequest;
142
- window.XMLHttpRequest = function() {
143
- this.xhr = new XHR();
144
- return this;
145
- }
146
- window.XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
147
- if(__fileNames.indexOf(url) >= 0) {
148
- this.file = url;
149
- this.responseText = __files[url];
150
- if(url.indexOf(".xml") === url.length - 4) {
151
- try {
152
- var oParser = new DOMParser();
153
- var oDOM = oParser.parseFromString(this.responseText, "text/xml");
154
- this.responseXML = oDOM;
155
- } catch(e) {}
156
- }
157
- // we indicate that the request is done
158
- this.readyState = 4;
159
- this.status = 200;
160
- } else {
161
- // pass thru to the normal xhr
162
- this.xhr.open(method, url, async, user, password);
163
- }
164
- };
165
- window.XMLHttpRequest.prototype.setRequestHeader = function(header, value) {
166
- if(this.file) return;
167
- return this.xhr.setRequestHeader(header, value);
168
- }
169
- window.XMLHttpRequest.prototype.abort = function() {
170
- return this.xhr.abort()
171
- }
172
- window.XMLHttpRequest.prototype.getAllResponseHeaders = function() {
173
- return this.xhr.getAllResponseHeaders();
174
- }
175
- window.XMLHttpRequest.prototype.getResponseHeader = function(header) {
176
- return this.xhr.getResponseHeader(header);
177
- }
178
- window.XMLHttpRequest.prototype.overrideMimeType = function(mime) {
179
- return this.xhr.overrideMimeType(mime);
180
- }
181
- window.XMLHttpRequest.prototype.send = function(data) {
182
- //we need to remap the fake XHR to the real one inside the onload/onreadystatechange functions
183
- var that = this;
184
- // unfortunately we need to do our copying of handlers in the next tick as
185
- // it seems with normal XHR you can add them after firing off send... which seems
186
- // unwise to do in the first place, but this is needed to support jQuery...
187
- setTimeout(function() {
188
- // we wire up all the listeners to the real XHR
189
- that.xhr.onerror = this.onerror;
190
- that.xhr.onprogress = this.onprogress;
191
- if(that.responseType || that.responseType === '')
192
- that.xhr.responseType = that.responseType
193
- // if the onload callback is used we need to copy over
194
- // the real response data to the fake object
195
- if(that.onload) {
196
- var onload = that.onload;
197
- that.xhr.onload = that.onload = function() {
198
- try{
199
- that.response = this.response;
200
- that.readyState = this.readyState;
201
- that.status = this.status;
202
- that.statusText = this.statusText;
203
- } catch(e) { console.log("onload", e) }
204
- try {
205
- if(that.responseType == '') {
206
- that.responseXML = this.responseXML;
207
- that.responseText = this.responseText;
208
- }
209
- if(that.responseType == 'text') {
210
- that.responseText = this.responseText;
211
- }
212
- } catch(e) { console.log("onload responseText/XML", e) }
213
- onload();
214
- }
215
- }
216
- // if the readystate change callback is used we need
217
- // to copy over the real response data to our fake xhr instance
218
- if(that.onreadystatechange) {
219
- var ready = that.onreadystatechange;
220
- that.xhr.onreadystatechange = function() {
221
- try{
222
- that.readyState = this.readyState;
223
- that.responseText = this.responseText;
224
- that.responseXML = this.responseXML;
225
- that.responseType = this.responseType;
226
- that.status = this.status;
227
- that.statusText = this.statusText;
228
- } catch(e){
229
- console.log("e", e)
230
- }
231
- ready();
232
- }
233
- }
234
- // if this request is for a local file, we short-circuit and just
235
- // end the request, since all the data should be on our fake request object
236
- if(that.file) {
237
- if(that.onreadystatechange)
238
- return that.onreadystatechange();
239
- if(that.onload)
240
- return that.onload(); //untested
241
- }
242
- // if this is a real request, we pass through the send call
243
- that.xhr.send(data)
244
- }, 0)
245
- }
246
-
247
- var originalFetch = window.fetch;
248
- window.fetch = function(input, init) {
249
-
250
- var url = input;
251
- if (input instanceof Request) {
252
- url = input.url
253
- }
254
-
255
- // This is a hack that seems to fix a problem with the way Mapbox is requesting its TileJSON
256
- // Not sure what blob:// protocol is anyway...
257
- if(typeof url === 'string') {
258
- url = url.replace('blob://', 'http://')
259
- }
260
-
261
- if(__fileNames.indexOf(url) >= 0) {
262
- var responseText = __files[url];
263
- return Promise.resolve({
264
- ok: true,
265
- status: 200,
266
- statusText: 'ok',
267
- url: url,
268
- text: function(){ return Promise.resolve(responseText) },
269
- json: function(){ return Promise.resolve(responseText).then(JSON.parse) },
270
- blob: function(){ return Promise.resolve(new Blob([responseText])) },
271
- // Inspired by https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
272
- arrayBuffer: function() {
273
- var buffer = new ArrayBuffer(responseText.length * 2);
274
- var bufferView = new Uint16Array(buffer);
275
- for (var i = 0, length = responseText.length; i < length; i++) {
276
- bufferView[i] = responseText.charCodeAt(i);
277
- }
278
- return Promise.resolve(buffer);
279
- }
280
- })
281
- }
282
-
283
- return originalFetch(input, init)
284
- }
285
-
286
- })()</script>`;
287
-
288
- template = xmlOverride + template;
289
-
290
- return template;
291
- }
@@ -1,42 +0,0 @@
1
- import { getText } from './getText';
2
-
3
- const EMPTY_PKG_JSON = {
4
- dependencies: {},
5
- vizhub: {},
6
- license: 'MIT',
7
- };
8
-
9
- export const packageJSON = (files) => {
10
- const packageJsonText = getText(files, 'package.json');
11
- try {
12
- const pkg = packageJsonText
13
- ? JSON.parse(packageJsonText)
14
- : EMPTY_PKG_JSON;
15
- return pkg;
16
- } catch (error) {
17
- console.log(error);
18
- return EMPTY_PKG_JSON;
19
- }
20
- };
21
-
22
- export const dependencies = (files) =>
23
- packageJSON(files).dependencies || {};
24
-
25
- export const getConfiguredLibraries = (files) => {
26
- const vizhubConfig = packageJSON(files).vizhub;
27
- return vizhubConfig ? vizhubConfig.libraries : {};
28
- };
29
-
30
- export const dependencySource = (
31
- { name, version },
32
- libraries,
33
- ) => {
34
- const path = libraries[name]
35
- ? libraries[name].path || ''
36
- : '';
37
- // unpkg uses file from unpkg or main field when no file specifid in url
38
- return `https://unpkg.com/${name}@${version}${path}`;
39
- };
40
-
41
- export const getLicense = (files) =>
42
- packageJSON(files).license || EMPTY_PKG_JSON.license;
@@ -1,18 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import {
3
- primordialViz,
4
- sampleReadmeText,
5
- } from 'entities/test/fixtures';
6
- import { transformFiles } from './transformFiles';
7
-
8
- describe('v2 transformFiles', () => {
9
- it('should transform files and exclude `index.html`', () => {
10
- expect(
11
- transformFiles(primordialViz.content.files),
12
- ).toEqual({
13
- 'README.md': {
14
- content: sampleReadmeText,
15
- },
16
- });
17
- });
18
- });
@@ -1,15 +0,0 @@
1
- import { FileV2, FilesV2 } from 'entities';
2
-
3
- // Transform files to the format expected by magicSandbox.
4
- export const transformFiles = (files: FilesV2) =>
5
- Object.values(files)
6
-
7
- // Filter out index.html, which is handled separately.
8
- .filter((file: FileV2) => file.name !== 'index.html')
9
-
10
- .reduce((accumulator, file) => {
11
- accumulator[file.name] = {
12
- content: file.text,
13
- };
14
- return accumulator;
15
- }, {});
@@ -1,20 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { primordialViz } from 'entities/test/fixtures';
3
- import { v3FilesToV2Files } from './v3FilesToV2Files';
4
-
5
- describe('v2 v3FilesToV2Files', () => {
6
- it('should compute correctly', () => {
7
- expect(
8
- v3FilesToV2Files(primordialViz.content.files),
9
- ).toEqual([
10
- {
11
- name: 'index.html',
12
- text: '<body style="font-size:26em">Hello</body>',
13
- },
14
- {
15
- name: 'README.md',
16
- text: 'Test [Markdown](https://www.markdownguide.org/).\n# Introduction\n\nThis is a test.',
17
- },
18
- ]);
19
- });
20
- });
@@ -1,14 +0,0 @@
1
- import { Files, FilesV2 } from 'entities';
2
-
3
- // Migrates V3 files to V2 files.
4
- export const v3FilesToV2Files = (files: Files): FilesV2 => {
5
- const v2Files: FilesV2 = [];
6
- for (const fileId in files) {
7
- const file = files[fileId];
8
- v2Files.push({
9
- name: file.name,
10
- text: file.text,
11
- });
12
- }
13
- return v2Files;
14
- };