@jsenv/core 27.0.0-alpha.75 → 27.0.0-alpha.76

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/dist/main.js CHANGED
@@ -969,7 +969,9 @@ const jsenvPluginNodeEsmResolver = ({
969
969
  fetchUrlContent: urlInfo => {
970
970
  if (urlInfo.url.startsWith("file:///@ignore/")) {
971
971
  return {
972
- content: "export default {}"
972
+ content: "export default {}",
973
+ contentType: "text/javascript",
974
+ type: "js_module"
973
975
  };
974
976
  }
975
977
 
@@ -1232,17 +1234,9 @@ const jsenvPluginFileUrls = ({
1232
1234
 
1233
1235
  const fileBuffer = readFileSync(urlObject);
1234
1236
  const contentType = CONTENT_TYPE.fromUrlExtension(urlInfo.url);
1235
-
1236
- if (CONTENT_TYPE.isTextual(contentType)) {
1237
- return {
1238
- contentType,
1239
- content: String(fileBuffer)
1240
- };
1241
- }
1242
-
1243
1237
  return {
1244
- contentType,
1245
- content: fileBuffer
1238
+ content: CONTENT_TYPE.isTextual(contentType) ? String(fileBuffer) : fileBuffer,
1239
+ contentType
1246
1240
  };
1247
1241
  }
1248
1242
  }];
@@ -1791,12 +1785,12 @@ const jsenvPluginDataUrls = () => {
1791
1785
  } = DATA_URL.parse(urlInfo.url);
1792
1786
  urlInfo.data.base64Flag = base64Flag;
1793
1787
  return {
1794
- contentType,
1795
1788
  content: contentFromUrlData({
1796
1789
  contentType,
1797
1790
  base64Flag,
1798
1791
  urlData
1799
- })
1792
+ }),
1793
+ contentType
1800
1794
  };
1801
1795
  },
1802
1796
  formatUrl: (reference, context) => {
@@ -1819,7 +1813,7 @@ const jsenvPluginDataUrls = () => {
1819
1813
  }
1820
1814
 
1821
1815
  const specifier = DATA_URL.stringify({
1822
- contentType: urlInfo.contentType,
1816
+ contentType: urlInfo.headers["content-type"],
1823
1817
  base64Flag: urlInfo.data.base64Flag,
1824
1818
  data: urlInfo.data.base64Flag ? dataToBase64(urlInfo.content) : String(urlInfo.content)
1825
1819
  });
@@ -1918,10 +1912,10 @@ const jsenvPluginInlineUrls = () => {
1918
1912
  }
1919
1913
 
1920
1914
  return {
1921
- contentType: urlInfo.contentType,
1922
1915
  // we want to fetch the original content otherwise we might re-cook
1923
1916
  // content already cooked
1924
- content: urlInfo.originalContent
1917
+ content: urlInfo.originalContent,
1918
+ contentType: urlInfo.contentType
1925
1919
  };
1926
1920
  }
1927
1921
  };
@@ -2571,14 +2565,14 @@ const jsenvPluginAsModules = () => {
2571
2565
 
2572
2566
  const jsonText = JSON.stringify(originalUrlInfo.content.trim());
2573
2567
  return {
2574
- originalUrl: originalUrlInfo.originalUrl,
2575
- originalContent: originalUrlInfo.originalContent,
2576
- type: "js_module",
2577
- contentType: "text/javascript",
2578
2568
  // here we could `export default ${jsonText}`:
2579
2569
  // but js engine are optimized to recognize JSON.parse
2580
2570
  // and use a faster parsing strategy
2581
- content: `export default JSON.parse(${jsonText})`
2571
+ content: `export default JSON.parse(${jsonText})`,
2572
+ contentType: "text/javascript",
2573
+ type: "js_module",
2574
+ originalUrl: originalUrlInfo.originalUrl,
2575
+ originalContent: originalUrlInfo.originalContent
2582
2576
  };
2583
2577
  }
2584
2578
  };
@@ -2604,16 +2598,16 @@ const jsenvPluginAsModules = () => {
2604
2598
  canUseTemplateString: true
2605
2599
  });
2606
2600
  return {
2607
- originalUrl: originalUrlInfo.originalUrl,
2608
- originalContent: originalUrlInfo.originalContent,
2609
- type: "js_module",
2610
- contentType: "text/javascript",
2611
2601
  content: `import { InlineContent } from ${JSON.stringify(inlineContentClientFileUrl)}
2612
2602
 
2613
2603
  const inlineContent = new InlineContent(${cssText}, { type: "text/css" })
2614
2604
  const stylesheet = new CSSStyleSheet()
2615
2605
  stylesheet.replaceSync(inlineContent.text)
2616
- export default stylesheet`
2606
+ export default stylesheet`,
2607
+ contentType: "text/javascript",
2608
+ type: "js_module",
2609
+ originalUrl: originalUrlInfo.originalUrl,
2610
+ originalContent: originalUrlInfo.originalContent
2617
2611
  };
2618
2612
  }
2619
2613
  };
@@ -2639,14 +2633,14 @@ const jsenvPluginAsModules = () => {
2639
2633
  canUseTemplateString: true
2640
2634
  });
2641
2635
  return {
2642
- originalUrl: originalUrlInfo.originalUrl,
2643
- originalContent: originalUrlInfo.originalContent,
2644
- type: "js_module",
2645
- contentType: "text/javascript",
2646
2636
  content: `import { InlineContent } from ${JSON.stringify(inlineContentClientFileUrl)}
2647
2637
 
2648
2638
  const inlineContent = new InlineContent(${textPlain}, { type: "text/plain" })
2649
- export default inlineContent.text`
2639
+ export default inlineContent.text`,
2640
+ contentType: "text/javascript",
2641
+ type: "js_module",
2642
+ originalUrl: originalUrlInfo.originalUrl,
2643
+ originalContent: originalUrlInfo.originalContent
2650
2644
  };
2651
2645
  }
2652
2646
  };
@@ -3130,11 +3124,11 @@ const jsenvPluginAsJsClassicConversion = ({
3130
3124
  });
3131
3125
  urlInfo.data.jsClassicFormat = jsClassicFormat;
3132
3126
  return {
3127
+ content,
3128
+ contentType: "text/javascript",
3129
+ type: "js_classic",
3133
3130
  originalUrl: originalUrlInfo.originalUrl,
3134
3131
  originalContent: originalUrlInfo.originalContent,
3135
- type: "js_classic",
3136
- contentType: "text/javascript",
3137
- content,
3138
3132
  sourcemap
3139
3133
  };
3140
3134
  }
@@ -6295,7 +6289,7 @@ const createUrlInfo = url => {
6295
6289
  sourcemap: null,
6296
6290
  sourcemapReference: null,
6297
6291
  timing: {},
6298
- responseHeaders: {}
6292
+ headers: {}
6299
6293
  };
6300
6294
  };
6301
6295
 
@@ -6593,14 +6587,15 @@ const returnValueAssertions = [{
6593
6587
  if (typeof valueReturned === "object") {
6594
6588
  const {
6595
6589
  shouldHandle,
6596
- content
6590
+ content,
6591
+ body
6597
6592
  } = valueReturned;
6598
6593
 
6599
6594
  if (shouldHandle === false) {
6600
6595
  return undefined;
6601
6596
  }
6602
6597
 
6603
- if (typeof content !== "string" && !Buffer.isBuffer(content)) {
6598
+ if (typeof content !== "string" && !Buffer.isBuffer(content) && !body) {
6604
6599
  throw new Error(`Unexpected "content" returned by plugin: it must be a string or a buffer; got ${content}`);
6605
6600
  }
6606
6601
 
@@ -7224,17 +7219,35 @@ const createKitchen = ({
7224
7219
  return;
7225
7220
  }
7226
7221
 
7227
- const {
7222
+ let {
7223
+ content,
7224
+ contentType,
7228
7225
  data,
7229
7226
  type,
7230
7227
  subtype,
7231
- contentType = "application/octet-stream",
7232
7228
  originalUrl,
7233
7229
  originalContent,
7234
- content,
7235
7230
  sourcemap,
7236
- filename
7231
+ filename,
7232
+ status = 200,
7233
+ headers = {},
7234
+ body
7237
7235
  } = fetchUrlContentReturnValue;
7236
+
7237
+ if (status !== 200) {
7238
+ throw new Error(`unexpected status, ${status}`);
7239
+ }
7240
+
7241
+ if (content === undefined) {
7242
+ content = body;
7243
+ }
7244
+
7245
+ if (contentType === undefined) {
7246
+ contentType = headers["content-type"] || "application/octet-stream";
7247
+ }
7248
+
7249
+ urlInfo.contentType = contentType;
7250
+ urlInfo.headers = headers;
7238
7251
  urlInfo.type = type || reference.expectedType || inferUrlInfoType({
7239
7252
  url: urlInfo.url,
7240
7253
  contentType
@@ -7243,8 +7256,7 @@ const createKitchen = ({
7243
7256
  url: urlInfo.url,
7244
7257
  type: urlInfo.type,
7245
7258
  subtype: urlInfo.subtype
7246
- });
7247
- urlInfo.contentType = contentType; // during build urls info are reused and load returns originalUrl/originalContent
7259
+ }); // during build urls info are reused and load returns originalUrl/originalContent
7248
7260
 
7249
7261
  urlInfo.originalUrl = originalUrl || urlInfo.originalUrl;
7250
7262
  urlInfo.originalContent = originalContent === undefined ? content : originalContent;
@@ -7969,7 +7981,7 @@ const createFileService = ({
7969
7981
  status: 304,
7970
7982
  headers: {
7971
7983
  "cache-control": `private,max-age=0,must-revalidate`,
7972
- ...urlInfo.responseHeaders
7984
+ ...urlInfo.headers
7973
7985
  }
7974
7986
  };
7975
7987
  }
@@ -7984,7 +7996,6 @@ const createFileService = ({
7984
7996
  urlInfo.type = null;
7985
7997
  urlInfo.subtype = null;
7986
7998
  urlInfo.timing = {};
7987
- urlInfo.responseHeaders = {};
7988
7999
  }
7989
8000
 
7990
8001
  const {
@@ -8000,10 +8011,7 @@ const createFileService = ({
8000
8011
  outDirectoryUrl: scenario === "dev" ? `${rootDirectoryUrl}.jsenv/${runtimeName}@${runtimeVersion}/` : `${rootDirectoryUrl}.jsenv/${scenario}/${runtimeName}@${runtimeVersion}/`
8001
8012
  });
8002
8013
  let {
8003
- response,
8004
- contentType,
8005
- content,
8006
- contentEtag
8014
+ response
8007
8015
  } = urlInfo;
8008
8016
 
8009
8017
  if (response) {
@@ -8014,13 +8022,13 @@ const createFileService = ({
8014
8022
  url: reference.url,
8015
8023
  status: 200,
8016
8024
  headers: {
8017
- "content-type": contentType,
8018
- "content-length": Buffer.byteLength(content),
8025
+ "content-length": Buffer.byteLength(urlInfo.content),
8019
8026
  "cache-control": `private,max-age=0,must-revalidate`,
8020
- "eTag": contentEtag,
8021
- ...urlInfo.responseHeaders
8027
+ "eTag": urlInfo.contentEtag,
8028
+ ...urlInfo.headers,
8029
+ "content-type": urlInfo.contentType
8022
8030
  },
8023
- body: content,
8031
+ body: urlInfo.content,
8024
8032
  timing: urlInfo.timing
8025
8033
  };
8026
8034
  kitchen.pluginController.callHooks("augmentResponse", {
@@ -12902,10 +12910,10 @@ const applyUrlVersioning = async ({
12902
12910
  const rawUrlInfo = rawGraph.getUrlInfo(rawUrls[versionedUrlInfo.url]);
12903
12911
  const finalUrlInfo = finalGraph.getUrlInfo(versionedUrlInfo.url);
12904
12912
  return {
12905
- originalContent: rawUrlInfo ? rawUrlInfo.originalContent : undefined,
12906
- sourcemap: finalUrlInfo ? finalUrlInfo.sourcemap : undefined,
12913
+ content: versionedUrlInfo.content,
12907
12914
  contentType: versionedUrlInfo.contentType,
12908
- content: versionedUrlInfo.content
12915
+ originalContent: rawUrlInfo ? rawUrlInfo.originalContent : undefined,
12916
+ sourcemap: finalUrlInfo ? finalUrlInfo.sourcemap : undefined
12909
12917
  };
12910
12918
  }
12911
12919
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/core",
3
- "version": "27.0.0-alpha.75",
3
+ "version": "27.0.0-alpha.76",
4
4
  "description": "Tool to develop, test and build js projects",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -68,7 +68,7 @@
68
68
  "@financial-times/polyfill-useragent-normaliser": "2.0.1",
69
69
  "@jsenv/abort": "4.1.2",
70
70
  "@jsenv/babel-plugins": "1.0.3",
71
- "@jsenv/filesystem": "4.0.5",
71
+ "@jsenv/filesystem": "4.0.6",
72
72
  "@jsenv/importmap": "1.2.0",
73
73
  "@jsenv/integrity": "0.0.1",
74
74
  "@jsenv/log": "1.6.3",
@@ -76,9 +76,9 @@
76
76
  "@jsenv/node-esm-resolution": "0.0.10",
77
77
  "@jsenv/server": "12.6.3",
78
78
  "@jsenv/uneval": "1.6.0",
79
- "@jsenv/utils": "1.8.8",
79
+ "@jsenv/utils": "1.8.9",
80
80
  "@jsenv/url-meta": "7.0.0",
81
- "@jsenv/urls": "1.2.2",
81
+ "@jsenv/urls": "1.2.3",
82
82
  "construct-style-sheets-polyfill": "3.1.0",
83
83
  "cssnano": "5.1.7",
84
84
  "cssnano-preset-default": "5.2.7",
@@ -1184,12 +1184,12 @@ const applyUrlVersioning = async ({
1184
1184
  )
1185
1185
  const finalUrlInfo = finalGraph.getUrlInfo(versionedUrlInfo.url)
1186
1186
  return {
1187
+ content: versionedUrlInfo.content,
1188
+ contentType: versionedUrlInfo.contentType,
1187
1189
  originalContent: rawUrlInfo
1188
1190
  ? rawUrlInfo.originalContent
1189
1191
  : undefined,
1190
1192
  sourcemap: finalUrlInfo ? finalUrlInfo.sourcemap : undefined,
1191
- contentType: versionedUrlInfo.contentType,
1192
- content: versionedUrlInfo.content,
1193
1193
  }
1194
1194
  }
1195
1195
  return versionedUrlInfo
@@ -272,24 +272,36 @@ export const createKitchen = ({
272
272
  )
273
273
  return
274
274
  }
275
- const {
275
+ let {
276
+ content,
277
+ contentType,
276
278
  data,
277
279
  type,
278
280
  subtype,
279
- contentType = "application/octet-stream",
280
281
  originalUrl,
281
282
  originalContent,
282
- content,
283
283
  sourcemap,
284
284
  filename,
285
+
286
+ status = 200,
287
+ headers = {},
288
+ body,
285
289
  } = fetchUrlContentReturnValue
290
+ if (status !== 200) {
291
+ throw new Error(`unexpected status, ${status}`)
292
+ }
293
+ if (content === undefined) {
294
+ content = body
295
+ }
296
+ if (contentType === undefined) {
297
+ contentType = headers["content-type"] || "application/octet-stream"
298
+ }
299
+ urlInfo.contentType = contentType
300
+ urlInfo.headers = headers
286
301
  urlInfo.type =
287
302
  type ||
288
303
  reference.expectedType ||
289
- inferUrlInfoType({
290
- url: urlInfo.url,
291
- contentType,
292
- })
304
+ inferUrlInfoType({ url: urlInfo.url, contentType })
293
305
  urlInfo.subtype =
294
306
  subtype ||
295
307
  reference.expectedSubtype ||
@@ -298,7 +310,6 @@ export const createKitchen = ({
298
310
  type: urlInfo.type,
299
311
  subtype: urlInfo.subtype,
300
312
  })
301
- urlInfo.contentType = contentType
302
313
  // during build urls info are reused and load returns originalUrl/originalContent
303
314
  urlInfo.originalUrl = originalUrl || urlInfo.originalUrl
304
315
  urlInfo.originalContent =
@@ -66,7 +66,7 @@ export const createFileService = ({
66
66
  status: 304,
67
67
  headers: {
68
68
  "cache-control": `private,max-age=0,must-revalidate`,
69
- ...urlInfo.responseHeaders,
69
+ ...urlInfo.headers,
70
70
  },
71
71
  }
72
72
  }
@@ -84,7 +84,6 @@ export const createFileService = ({
84
84
  urlInfo.type = null
85
85
  urlInfo.subtype = null
86
86
  urlInfo.timing = {}
87
- urlInfo.responseHeaders = {}
88
87
  }
89
88
  const { runtimeName, runtimeVersion } = parseUserAgentHeader(
90
89
  request.headers["user-agent"],
@@ -100,7 +99,7 @@ export const createFileService = ({
100
99
  ? `${rootDirectoryUrl}.jsenv/${runtimeName}@${runtimeVersion}/`
101
100
  : `${rootDirectoryUrl}.jsenv/${scenario}/${runtimeName}@${runtimeVersion}/`,
102
101
  })
103
- let { response, contentType, content, contentEtag } = urlInfo
102
+ let { response } = urlInfo
104
103
  if (response) {
105
104
  return response
106
105
  }
@@ -108,13 +107,13 @@ export const createFileService = ({
108
107
  url: reference.url,
109
108
  status: 200,
110
109
  headers: {
111
- "content-type": contentType,
112
- "content-length": Buffer.byteLength(content),
110
+ "content-length": Buffer.byteLength(urlInfo.content),
113
111
  "cache-control": `private,max-age=0,must-revalidate`,
114
- "eTag": contentEtag,
115
- ...urlInfo.responseHeaders,
112
+ "eTag": urlInfo.contentEtag,
113
+ ...urlInfo.headers,
114
+ "content-type": urlInfo.contentType,
116
115
  },
117
- body: content,
116
+ body: urlInfo.content,
118
117
  timing: urlInfo.timing,
119
118
  }
120
119
  kitchen.pluginController.callHooks(
@@ -196,6 +196,6 @@ const createUrlInfo = (url) => {
196
196
  sourcemap: null,
197
197
  sourcemapReference: null,
198
198
  timing: {},
199
- responseHeaders: {},
199
+ headers: {},
200
200
  }
201
201
  }
@@ -178,15 +178,11 @@ export const jsenvPluginFileUrls = ({
178
178
  }
179
179
  const fileBuffer = readFileSync(urlObject)
180
180
  const contentType = CONTENT_TYPE.fromUrlExtension(urlInfo.url)
181
- if (CONTENT_TYPE.isTextual(contentType)) {
182
- return {
183
- contentType,
184
- content: String(fileBuffer),
185
- }
186
- }
187
181
  return {
182
+ content: CONTENT_TYPE.isTextual(contentType)
183
+ ? String(fileBuffer)
184
+ : fileBuffer,
188
185
  contentType,
189
- content: fileBuffer,
190
186
  }
191
187
  },
192
188
  },
@@ -22,8 +22,8 @@ export const jsenvPluginDataUrls = () => {
22
22
  } = DATA_URL.parse(urlInfo.url)
23
23
  urlInfo.data.base64Flag = base64Flag
24
24
  return {
25
- contentType,
26
25
  content: contentFromUrlData({ contentType, base64Flag, urlData }),
26
+ contentType,
27
27
  }
28
28
  },
29
29
  formatUrl: (reference, context) => {
@@ -40,7 +40,7 @@ export const jsenvPluginDataUrls = () => {
40
40
  return reference.generatedUrl
41
41
  }
42
42
  const specifier = DATA_URL.stringify({
43
- contentType: urlInfo.contentType,
43
+ contentType: urlInfo.headers["content-type"],
44
44
  base64Flag: urlInfo.data.base64Flag,
45
45
  data: urlInfo.data.base64Flag
46
46
  ? dataToBase64(urlInfo.content)
@@ -26,10 +26,10 @@ const jsenvPluginInlineUrls = () => {
26
26
  return null
27
27
  }
28
28
  return {
29
- contentType: urlInfo.contentType,
30
29
  // we want to fetch the original content otherwise we might re-cook
31
30
  // content already cooked
32
31
  content: urlInfo.originalContent,
32
+ contentType: urlInfo.contentType,
33
33
  }
34
34
  },
35
35
  }
@@ -110,6 +110,8 @@ const jsenvPluginNodeEsmResolver = ({
110
110
  if (urlInfo.url.startsWith("file:///@ignore/")) {
111
111
  return {
112
112
  content: "export default {}",
113
+ contentType: "text/javascript",
114
+ type: "js_module",
113
115
  }
114
116
  }
115
117
  return null
@@ -266,11 +266,11 @@ const returnValueAssertions = [
266
266
  return { content: valueReturned }
267
267
  }
268
268
  if (typeof valueReturned === "object") {
269
- const { shouldHandle, content } = valueReturned
269
+ const { shouldHandle, content, body } = valueReturned
270
270
  if (shouldHandle === false) {
271
271
  return undefined
272
272
  }
273
- if (typeof content !== "string" && !Buffer.isBuffer(content)) {
273
+ if (typeof content !== "string" && !Buffer.isBuffer(content) && !body) {
274
274
  throw new Error(
275
275
  `Unexpected "content" returned by plugin: it must be a string or a buffer; got ${content}`,
276
276
  )
@@ -123,11 +123,11 @@ const jsenvPluginAsJsClassicConversion = ({
123
123
  })
124
124
  urlInfo.data.jsClassicFormat = jsClassicFormat
125
125
  return {
126
+ content,
127
+ contentType: "text/javascript",
128
+ type: "js_classic",
126
129
  originalUrl: originalUrlInfo.originalUrl,
127
130
  originalContent: originalUrlInfo.originalContent,
128
- type: "js_classic",
129
- contentType: "text/javascript",
130
- content,
131
131
  sourcemap,
132
132
  }
133
133
  },
@@ -98,14 +98,14 @@ const jsenvPluginAsModules = () => {
98
98
  }
99
99
  const jsonText = JSON.stringify(originalUrlInfo.content.trim())
100
100
  return {
101
- originalUrl: originalUrlInfo.originalUrl,
102
- originalContent: originalUrlInfo.originalContent,
103
- type: "js_module",
104
- contentType: "text/javascript",
105
101
  // here we could `export default ${jsonText}`:
106
102
  // but js engine are optimized to recognize JSON.parse
107
103
  // and use a faster parsing strategy
108
104
  content: `export default JSON.parse(${jsonText})`,
105
+ contentType: "text/javascript",
106
+ type: "js_module",
107
+ originalUrl: originalUrlInfo.originalUrl,
108
+ originalContent: originalUrlInfo.originalContent,
109
109
  }
110
110
  },
111
111
  }
@@ -130,10 +130,6 @@ const jsenvPluginAsModules = () => {
130
130
  canUseTemplateString: true,
131
131
  })
132
132
  return {
133
- originalUrl: originalUrlInfo.originalUrl,
134
- originalContent: originalUrlInfo.originalContent,
135
- type: "js_module",
136
- contentType: "text/javascript",
137
133
  content: `import { InlineContent } from ${JSON.stringify(
138
134
  inlineContentClientFileUrl,
139
135
  )}
@@ -142,6 +138,10 @@ const jsenvPluginAsModules = () => {
142
138
  const stylesheet = new CSSStyleSheet()
143
139
  stylesheet.replaceSync(inlineContent.text)
144
140
  export default stylesheet`,
141
+ contentType: "text/javascript",
142
+ type: "js_module",
143
+ originalUrl: originalUrlInfo.originalUrl,
144
+ originalContent: originalUrlInfo.originalContent,
145
145
  }
146
146
  },
147
147
  }
@@ -166,16 +166,16 @@ const jsenvPluginAsModules = () => {
166
166
  canUseTemplateString: true,
167
167
  })
168
168
  return {
169
- originalUrl: originalUrlInfo.originalUrl,
170
- originalContent: originalUrlInfo.originalContent,
171
- type: "js_module",
172
- contentType: "text/javascript",
173
169
  content: `import { InlineContent } from ${JSON.stringify(
174
170
  inlineContentClientFileUrl,
175
171
  )}
176
172
 
177
173
  const inlineContent = new InlineContent(${textPlain}, { type: "text/plain" })
178
174
  export default inlineContent.text`,
175
+ contentType: "text/javascript",
176
+ type: "js_module",
177
+ originalUrl: originalUrlInfo.originalUrl,
178
+ originalContent: originalUrlInfo.originalContent,
179
179
  }
180
180
  },
181
181
  }