html-minifier-next 5.1.1 → 5.1.2
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/htmlminifier.cjs +53 -30
- package/dist/types/htmlminifier.d.ts.map +1 -1
- package/dist/types/lib/attributes.d.ts.map +1 -1
- package/dist/types/lib/whitespace.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/htmlminifier.js +13 -7
- package/src/lib/attributes.js +35 -21
- package/src/lib/whitespace.js +5 -2
package/dist/htmlminifier.cjs
CHANGED
|
@@ -1385,12 +1385,15 @@ function collapseWhitespaceSmart(str, prevTag, nextTag, prevAttrs, nextAttrs, op
|
|
|
1385
1385
|
|
|
1386
1386
|
// Collapse/trim whitespace for given tag
|
|
1387
1387
|
|
|
1388
|
+
const noCollapseWsTags = new Set(['script', 'style', 'pre', 'textarea']);
|
|
1389
|
+
const noTrimWsTags = new Set(['pre', 'textarea']);
|
|
1390
|
+
|
|
1388
1391
|
function canCollapseWhitespace(tag) {
|
|
1389
|
-
return
|
|
1392
|
+
return !noCollapseWsTags.has(tag);
|
|
1390
1393
|
}
|
|
1391
1394
|
|
|
1392
1395
|
function canTrimWhitespace(tag) {
|
|
1393
|
-
return
|
|
1396
|
+
return !noTrimWsTags.has(tag);
|
|
1394
1397
|
}
|
|
1395
1398
|
|
|
1396
1399
|
/**
|
|
@@ -2220,31 +2223,45 @@ function isBooleanAttribute(attrName, attrValue) {
|
|
|
2220
2223
|
(attrValue === '' && emptyCollapsible.has(attrName));
|
|
2221
2224
|
}
|
|
2222
2225
|
|
|
2226
|
+
const uriTypeAttributes = new Map([
|
|
2227
|
+
['a', new Set(['href'])],
|
|
2228
|
+
['area', new Set(['href'])],
|
|
2229
|
+
['link', new Set(['href'])],
|
|
2230
|
+
['base', new Set(['href'])],
|
|
2231
|
+
['img', new Set(['src', 'longdesc', 'usemap'])],
|
|
2232
|
+
['object', new Set(['classid', 'codebase', 'data', 'usemap'])],
|
|
2233
|
+
['q', new Set(['cite'])],
|
|
2234
|
+
['blockquote', new Set(['cite'])],
|
|
2235
|
+
['ins', new Set(['cite'])],
|
|
2236
|
+
['del', new Set(['cite'])],
|
|
2237
|
+
['form', new Set(['action'])],
|
|
2238
|
+
['input', new Set(['src', 'usemap'])],
|
|
2239
|
+
['head', new Set(['profile'])],
|
|
2240
|
+
['script', new Set(['src', 'for'])]
|
|
2241
|
+
]);
|
|
2242
|
+
|
|
2223
2243
|
function isUriTypeAttribute(attrName, tag) {
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
(tag === 'img' && /^(?:src|longdesc|usemap)$/.test(attrName)) ||
|
|
2227
|
-
(tag === 'object' && /^(?:classid|codebase|data|usemap)$/.test(attrName)) ||
|
|
2228
|
-
(tag === 'q' && attrName === 'cite') ||
|
|
2229
|
-
(tag === 'blockquote' && attrName === 'cite') ||
|
|
2230
|
-
((tag === 'ins' || tag === 'del') && attrName === 'cite') ||
|
|
2231
|
-
(tag === 'form' && attrName === 'action') ||
|
|
2232
|
-
(tag === 'input' && (attrName === 'src' || attrName === 'usemap')) ||
|
|
2233
|
-
(tag === 'head' && attrName === 'profile') ||
|
|
2234
|
-
(tag === 'script' && (attrName === 'src' || attrName === 'for'))
|
|
2235
|
-
);
|
|
2244
|
+
const set = uriTypeAttributes.get(tag);
|
|
2245
|
+
return set ? set.has(attrName) : false;
|
|
2236
2246
|
}
|
|
2237
2247
|
|
|
2248
|
+
const numberTypeAttributes = new Map([
|
|
2249
|
+
['a', new Set(['tabindex'])],
|
|
2250
|
+
['area', new Set(['tabindex'])],
|
|
2251
|
+
['object', new Set(['tabindex'])],
|
|
2252
|
+
['button', new Set(['tabindex'])],
|
|
2253
|
+
['input', new Set(['maxlength', 'tabindex'])],
|
|
2254
|
+
['select', new Set(['size', 'tabindex'])],
|
|
2255
|
+
['textarea', new Set(['rows', 'cols', 'tabindex'])],
|
|
2256
|
+
['colgroup', new Set(['span'])],
|
|
2257
|
+
['col', new Set(['span'])],
|
|
2258
|
+
['th', new Set(['rowspan', 'colspan'])],
|
|
2259
|
+
['td', new Set(['rowspan', 'colspan'])]
|
|
2260
|
+
]);
|
|
2261
|
+
|
|
2238
2262
|
function isNumberTypeAttribute(attrName, tag) {
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
(tag === 'input' && (attrName === 'maxlength' || attrName === 'tabindex')) ||
|
|
2242
|
-
(tag === 'select' && (attrName === 'size' || attrName === 'tabindex')) ||
|
|
2243
|
-
(tag === 'textarea' && /^(?:rows|cols|tabindex)$/.test(attrName)) ||
|
|
2244
|
-
(tag === 'colgroup' && attrName === 'span') ||
|
|
2245
|
-
(tag === 'col' && attrName === 'span') ||
|
|
2246
|
-
((tag === 'th' || tag === 'td') && (attrName === 'rowspan' || attrName === 'colspan'))
|
|
2247
|
-
);
|
|
2263
|
+
const set = numberTypeAttributes.get(tag);
|
|
2264
|
+
return set ? set.has(attrName) : false;
|
|
2248
2265
|
}
|
|
2249
2266
|
|
|
2250
2267
|
function isLinkType(tag, attrs, value) {
|
|
@@ -3691,6 +3708,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
3691
3708
|
let currentAttrs = [];
|
|
3692
3709
|
const stackNoTrimWhitespace = [];
|
|
3693
3710
|
const stackNoCollapseWhitespace = [];
|
|
3711
|
+
let preTextareaDepth = 0; // Count of `pre`/`textarea` entries in `stackNoTrimWhitespace`
|
|
3694
3712
|
let optionalStartTag = '';
|
|
3695
3713
|
let optionalEndTag = '';
|
|
3696
3714
|
let optionalEndTagEmitted = false;
|
|
@@ -3851,7 +3869,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
3851
3869
|
let charsIndex = buffer.length - 1;
|
|
3852
3870
|
if (buffer.length > 1) {
|
|
3853
3871
|
const item = buffer[buffer.length - 1];
|
|
3854
|
-
if (/^(?:<!|$)/.test(item) && item.indexOf(uidIgnore) === -1) {
|
|
3872
|
+
if (/^(?:<!|$)/.test(item) && (!uidIgnore || item.indexOf(uidIgnore) === -1)) {
|
|
3855
3873
|
charsIndex--;
|
|
3856
3874
|
}
|
|
3857
3875
|
}
|
|
@@ -3945,6 +3963,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
3945
3963
|
if (!unary) {
|
|
3946
3964
|
if (!canTrimWhitespace$1(tag, attrs) || stackNoTrimWhitespace.length) {
|
|
3947
3965
|
stackNoTrimWhitespace.push(tag);
|
|
3966
|
+
if (tag === 'pre' || tag === 'textarea') preTextareaDepth++;
|
|
3948
3967
|
}
|
|
3949
3968
|
if (!canCollapseWhitespace$1(tag, attrs) || stackNoCollapseWhitespace.length) {
|
|
3950
3969
|
stackNoCollapseWhitespace.push(tag);
|
|
@@ -3974,11 +3993,14 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
3974
3993
|
options.sortAttributes(tag, attrs);
|
|
3975
3994
|
}
|
|
3976
3995
|
|
|
3996
|
+
const normalizedAttrs = await Promise.all(
|
|
3997
|
+
attrs.map(attr => normalizeAttr(attr, attrs, tag, options, minifyHTML))
|
|
3998
|
+
);
|
|
3977
3999
|
const parts = [];
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
if (
|
|
3981
|
-
parts.push(buildAttr(
|
|
4000
|
+
let isLast = true;
|
|
4001
|
+
for (let i = normalizedAttrs.length - 1; i >= 0; i--) {
|
|
4002
|
+
if (normalizedAttrs[i]) {
|
|
4003
|
+
parts.push(buildAttr(normalizedAttrs[i], hasUnarySlash, options, isLast, uidAttr));
|
|
3982
4004
|
isLast = false;
|
|
3983
4005
|
}
|
|
3984
4006
|
}
|
|
@@ -4014,6 +4036,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
4014
4036
|
if (options.collapseWhitespace) {
|
|
4015
4037
|
if (stackNoTrimWhitespace.length) {
|
|
4016
4038
|
if (tag === stackNoTrimWhitespace[stackNoTrimWhitespace.length - 1]) {
|
|
4039
|
+
if (tag === 'pre' || tag === 'textarea') preTextareaDepth--;
|
|
4017
4040
|
stackNoTrimWhitespace.pop();
|
|
4018
4041
|
}
|
|
4019
4042
|
} else {
|
|
@@ -4115,7 +4138,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
4115
4138
|
// Only trims single trailing newlines (multiple newlines are likely intentional formatting)
|
|
4116
4139
|
if (options.collapseWhitespace && stackNoTrimWhitespace.length) {
|
|
4117
4140
|
const topTag = stackNoTrimWhitespace[stackNoTrimWhitespace.length - 1];
|
|
4118
|
-
if (
|
|
4141
|
+
if (preTextareaDepth > 0) {
|
|
4119
4142
|
// Trim trailing whitespace only if it ends with a single newline (not multiple)
|
|
4120
4143
|
// Multiple newlines are likely intentional formatting, single newline is often a template artifact
|
|
4121
4144
|
// Treat CRLF (`\r\n`), CR (`\r`), and LF (`\n`) as single line-ending units
|
|
@@ -4128,7 +4151,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
4128
4151
|
if (!stackNoTrimWhitespace.length) {
|
|
4129
4152
|
if (prevTag === 'comment') {
|
|
4130
4153
|
const prevComment = buffer[buffer.length - 1];
|
|
4131
|
-
if (prevComment.indexOf(uidIgnore) === -1) {
|
|
4154
|
+
if (!uidIgnore || prevComment.indexOf(uidIgnore) === -1) {
|
|
4132
4155
|
if (!prevComment) {
|
|
4133
4156
|
prevTag = charsPrevTag;
|
|
4134
4157
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"htmlminifier.d.ts","sourceRoot":"","sources":["../../src/htmlminifier.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"htmlminifier.d.ts","sourceRoot":"","sources":["../../src/htmlminifier.js"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attributes.d.ts","sourceRoot":"","sources":["../../../src/lib/attributes.js"],"names":[],"mappings":"AAmCA,yDAEC;AAED,mEAOC;AAED,uEAWC;AAED,8DAGC;AAED,4EAOC;AAgCD,mGAuCC;AAED,mEAGC;AAED,qEAGC;AAED,kEAWC;AAED,sEAGC;AAED,8DAWC;AAED,2EAIC;
|
|
1
|
+
{"version":3,"file":"attributes.d.ts","sourceRoot":"","sources":["../../../src/lib/attributes.js"],"names":[],"mappings":"AAmCA,yDAEC;AAED,mEAOC;AAED,uEAWC;AAED,8DAGC;AAED,4EAOC;AAgCD,mGAuCC;AAED,mEAGC;AAED,qEAGC;AAED,kEAWC;AAED,sEAGC;AAED,8DAWC;AAED,2EAIC;AAmBD,qEAGC;AAgBD,wEAGC;AAED,sEAUC;AAED,2EAEC;AAED,2DAEC;AAED,8DAUC;AAED,uEAUC;AAED,oGASC;AAED,4DAOC;AAID,0IAqIC;AAsBD;;;;GAsCC;AAED,6GAuHC;AA3hBD;;;;;;;GAOG;AACH,mEAHW,OAAO,SAuBjB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whitespace.d.ts","sourceRoot":"","sources":["../../../src/lib/whitespace.js"],"names":[],"mappings":"AAiBA,8CAOC;AAID,qDAgBC;AAID,iHAqFC;AAID,0KAwEC;
|
|
1
|
+
{"version":3,"file":"whitespace.d.ts","sourceRoot":"","sources":["../../../src/lib/whitespace.js"],"names":[],"mappings":"AAiBA,8CAOC;AAID,qDAgBC;AAID,iHAqFC;AAID,0KAwEC;AAOD,yDAEC;AAED,qDAEC"}
|
package/package.json
CHANGED
package/src/htmlminifier.js
CHANGED
|
@@ -895,6 +895,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
895
895
|
let currentAttrs = [];
|
|
896
896
|
const stackNoTrimWhitespace = [];
|
|
897
897
|
const stackNoCollapseWhitespace = [];
|
|
898
|
+
let preTextareaDepth = 0; // Count of `pre`/`textarea` entries in `stackNoTrimWhitespace`
|
|
898
899
|
let optionalStartTag = '';
|
|
899
900
|
let optionalEndTag = '';
|
|
900
901
|
let optionalEndTagEmitted = false;
|
|
@@ -1055,7 +1056,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
1055
1056
|
let charsIndex = buffer.length - 1;
|
|
1056
1057
|
if (buffer.length > 1) {
|
|
1057
1058
|
const item = buffer[buffer.length - 1];
|
|
1058
|
-
if (/^(?:<!|$)/.test(item) && item.indexOf(uidIgnore) === -1) {
|
|
1059
|
+
if (/^(?:<!|$)/.test(item) && (!uidIgnore || item.indexOf(uidIgnore) === -1)) {
|
|
1059
1060
|
charsIndex--;
|
|
1060
1061
|
}
|
|
1061
1062
|
}
|
|
@@ -1149,6 +1150,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
1149
1150
|
if (!unary) {
|
|
1150
1151
|
if (!canTrimWhitespace(tag, attrs) || stackNoTrimWhitespace.length) {
|
|
1151
1152
|
stackNoTrimWhitespace.push(tag);
|
|
1153
|
+
if (tag === 'pre' || tag === 'textarea') preTextareaDepth++;
|
|
1152
1154
|
}
|
|
1153
1155
|
if (!canCollapseWhitespace(tag, attrs) || stackNoCollapseWhitespace.length) {
|
|
1154
1156
|
stackNoCollapseWhitespace.push(tag);
|
|
@@ -1178,11 +1180,14 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
1178
1180
|
options.sortAttributes(tag, attrs);
|
|
1179
1181
|
}
|
|
1180
1182
|
|
|
1183
|
+
const normalizedAttrs = await Promise.all(
|
|
1184
|
+
attrs.map(attr => normalizeAttr(attr, attrs, tag, options, minifyHTML))
|
|
1185
|
+
);
|
|
1181
1186
|
const parts = [];
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
if (
|
|
1185
|
-
parts.push(buildAttr(
|
|
1187
|
+
let isLast = true;
|
|
1188
|
+
for (let i = normalizedAttrs.length - 1; i >= 0; i--) {
|
|
1189
|
+
if (normalizedAttrs[i]) {
|
|
1190
|
+
parts.push(buildAttr(normalizedAttrs[i], hasUnarySlash, options, isLast, uidAttr));
|
|
1186
1191
|
isLast = false;
|
|
1187
1192
|
}
|
|
1188
1193
|
}
|
|
@@ -1218,6 +1223,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
1218
1223
|
if (options.collapseWhitespace) {
|
|
1219
1224
|
if (stackNoTrimWhitespace.length) {
|
|
1220
1225
|
if (tag === stackNoTrimWhitespace[stackNoTrimWhitespace.length - 1]) {
|
|
1226
|
+
if (tag === 'pre' || tag === 'textarea') preTextareaDepth--;
|
|
1221
1227
|
stackNoTrimWhitespace.pop();
|
|
1222
1228
|
}
|
|
1223
1229
|
} else {
|
|
@@ -1319,7 +1325,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
1319
1325
|
// Only trims single trailing newlines (multiple newlines are likely intentional formatting)
|
|
1320
1326
|
if (options.collapseWhitespace && stackNoTrimWhitespace.length) {
|
|
1321
1327
|
const topTag = stackNoTrimWhitespace[stackNoTrimWhitespace.length - 1];
|
|
1322
|
-
if (
|
|
1328
|
+
if (preTextareaDepth > 0) {
|
|
1323
1329
|
// Trim trailing whitespace only if it ends with a single newline (not multiple)
|
|
1324
1330
|
// Multiple newlines are likely intentional formatting, single newline is often a template artifact
|
|
1325
1331
|
// Treat CRLF (`\r\n`), CR (`\r`), and LF (`\n`) as single line-ending units
|
|
@@ -1332,7 +1338,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
1332
1338
|
if (!stackNoTrimWhitespace.length) {
|
|
1333
1339
|
if (prevTag === 'comment') {
|
|
1334
1340
|
const prevComment = buffer[buffer.length - 1];
|
|
1335
|
-
if (prevComment.indexOf(uidIgnore) === -1) {
|
|
1341
|
+
if (!uidIgnore || prevComment.indexOf(uidIgnore) === -1) {
|
|
1336
1342
|
if (!prevComment) {
|
|
1337
1343
|
prevTag = charsPrevTag;
|
|
1338
1344
|
}
|
package/src/lib/attributes.js
CHANGED
|
@@ -191,31 +191,45 @@ function isBooleanAttribute(attrName, attrValue) {
|
|
|
191
191
|
(attrValue === '' && emptyCollapsible.has(attrName));
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
+
const uriTypeAttributes = new Map([
|
|
195
|
+
['a', new Set(['href'])],
|
|
196
|
+
['area', new Set(['href'])],
|
|
197
|
+
['link', new Set(['href'])],
|
|
198
|
+
['base', new Set(['href'])],
|
|
199
|
+
['img', new Set(['src', 'longdesc', 'usemap'])],
|
|
200
|
+
['object', new Set(['classid', 'codebase', 'data', 'usemap'])],
|
|
201
|
+
['q', new Set(['cite'])],
|
|
202
|
+
['blockquote', new Set(['cite'])],
|
|
203
|
+
['ins', new Set(['cite'])],
|
|
204
|
+
['del', new Set(['cite'])],
|
|
205
|
+
['form', new Set(['action'])],
|
|
206
|
+
['input', new Set(['src', 'usemap'])],
|
|
207
|
+
['head', new Set(['profile'])],
|
|
208
|
+
['script', new Set(['src', 'for'])]
|
|
209
|
+
]);
|
|
210
|
+
|
|
194
211
|
function isUriTypeAttribute(attrName, tag) {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
(tag === 'img' && /^(?:src|longdesc|usemap)$/.test(attrName)) ||
|
|
198
|
-
(tag === 'object' && /^(?:classid|codebase|data|usemap)$/.test(attrName)) ||
|
|
199
|
-
(tag === 'q' && attrName === 'cite') ||
|
|
200
|
-
(tag === 'blockquote' && attrName === 'cite') ||
|
|
201
|
-
((tag === 'ins' || tag === 'del') && attrName === 'cite') ||
|
|
202
|
-
(tag === 'form' && attrName === 'action') ||
|
|
203
|
-
(tag === 'input' && (attrName === 'src' || attrName === 'usemap')) ||
|
|
204
|
-
(tag === 'head' && attrName === 'profile') ||
|
|
205
|
-
(tag === 'script' && (attrName === 'src' || attrName === 'for'))
|
|
206
|
-
);
|
|
212
|
+
const set = uriTypeAttributes.get(tag);
|
|
213
|
+
return set ? set.has(attrName) : false;
|
|
207
214
|
}
|
|
208
215
|
|
|
216
|
+
const numberTypeAttributes = new Map([
|
|
217
|
+
['a', new Set(['tabindex'])],
|
|
218
|
+
['area', new Set(['tabindex'])],
|
|
219
|
+
['object', new Set(['tabindex'])],
|
|
220
|
+
['button', new Set(['tabindex'])],
|
|
221
|
+
['input', new Set(['maxlength', 'tabindex'])],
|
|
222
|
+
['select', new Set(['size', 'tabindex'])],
|
|
223
|
+
['textarea', new Set(['rows', 'cols', 'tabindex'])],
|
|
224
|
+
['colgroup', new Set(['span'])],
|
|
225
|
+
['col', new Set(['span'])],
|
|
226
|
+
['th', new Set(['rowspan', 'colspan'])],
|
|
227
|
+
['td', new Set(['rowspan', 'colspan'])]
|
|
228
|
+
]);
|
|
229
|
+
|
|
209
230
|
function isNumberTypeAttribute(attrName, tag) {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
(tag === 'input' && (attrName === 'maxlength' || attrName === 'tabindex')) ||
|
|
213
|
-
(tag === 'select' && (attrName === 'size' || attrName === 'tabindex')) ||
|
|
214
|
-
(tag === 'textarea' && /^(?:rows|cols|tabindex)$/.test(attrName)) ||
|
|
215
|
-
(tag === 'colgroup' && attrName === 'span') ||
|
|
216
|
-
(tag === 'col' && attrName === 'span') ||
|
|
217
|
-
((tag === 'th' || tag === 'td') && (attrName === 'rowspan' || attrName === 'colspan'))
|
|
218
|
-
);
|
|
231
|
+
const set = numberTypeAttributes.get(tag);
|
|
232
|
+
return set ? set.has(attrName) : false;
|
|
219
233
|
}
|
|
220
234
|
|
|
221
235
|
function isLinkType(tag, attrs, value) {
|
package/src/lib/whitespace.js
CHANGED
|
@@ -211,12 +211,15 @@ function collapseWhitespaceSmart(str, prevTag, nextTag, prevAttrs, nextAttrs, op
|
|
|
211
211
|
|
|
212
212
|
// Collapse/trim whitespace for given tag
|
|
213
213
|
|
|
214
|
+
const noCollapseWsTags = new Set(['script', 'style', 'pre', 'textarea']);
|
|
215
|
+
const noTrimWsTags = new Set(['pre', 'textarea']);
|
|
216
|
+
|
|
214
217
|
function canCollapseWhitespace(tag) {
|
|
215
|
-
return
|
|
218
|
+
return !noCollapseWsTags.has(tag);
|
|
216
219
|
}
|
|
217
220
|
|
|
218
221
|
function canTrimWhitespace(tag) {
|
|
219
|
-
return
|
|
222
|
+
return !noTrimWsTags.has(tag);
|
|
220
223
|
}
|
|
221
224
|
|
|
222
225
|
// Exports
|