@unhead/shared 1.11.13 → 1.11.15
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/index.cjs +11 -101
- package/dist/index.mjs +8 -98
- package/package.json +3 -5
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const packrup = require('packrup');
|
|
4
|
+
|
|
5
|
+
function asArray(value) {
|
|
4
6
|
return Array.isArray(value) ? value : [value];
|
|
5
7
|
}
|
|
6
8
|
|
|
@@ -64,102 +66,6 @@ function hashTag(tag) {
|
|
|
64
66
|
return hashCode(content);
|
|
65
67
|
}
|
|
66
68
|
|
|
67
|
-
function asArray(input) {
|
|
68
|
-
return Array.isArray(input) ? input : [input];
|
|
69
|
-
}
|
|
70
|
-
const InternalKeySymbol = "_$key";
|
|
71
|
-
function packObject(input, options) {
|
|
72
|
-
const keys = Object.keys(input);
|
|
73
|
-
let [k, v] = keys;
|
|
74
|
-
options = options || {};
|
|
75
|
-
options.key = options.key || k;
|
|
76
|
-
options.value = options.value || v;
|
|
77
|
-
options.resolveKey = options.resolveKey || ((k2) => k2);
|
|
78
|
-
const resolveKey = (index) => {
|
|
79
|
-
const arr = asArray(options[index]);
|
|
80
|
-
return arr.find((k2) => {
|
|
81
|
-
if (typeof k2 === "string" && k2.includes(".")) {
|
|
82
|
-
return k2;
|
|
83
|
-
}
|
|
84
|
-
return k2 && keys.includes(k2);
|
|
85
|
-
});
|
|
86
|
-
};
|
|
87
|
-
const resolveValue = (k2, input2) => {
|
|
88
|
-
if (k2.includes(".")) {
|
|
89
|
-
const paths = k2.split(".");
|
|
90
|
-
let val = input2;
|
|
91
|
-
for (const path of paths)
|
|
92
|
-
val = val[path];
|
|
93
|
-
return val;
|
|
94
|
-
}
|
|
95
|
-
return input2[k2];
|
|
96
|
-
};
|
|
97
|
-
k = resolveKey("key") || k;
|
|
98
|
-
v = resolveKey("value") || v;
|
|
99
|
-
const dedupeKeyPrefix = input.key ? `${InternalKeySymbol}${input.key}-` : "";
|
|
100
|
-
let keyValue = resolveValue(k, input);
|
|
101
|
-
keyValue = options.resolveKey(keyValue);
|
|
102
|
-
return {
|
|
103
|
-
[`${dedupeKeyPrefix}${keyValue}`]: resolveValue(v, input)
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function packArray(input, options) {
|
|
108
|
-
const packed = {};
|
|
109
|
-
for (const i of input) {
|
|
110
|
-
const packedObj = packObject(i, options);
|
|
111
|
-
const pKey = Object.keys(packedObj)[0];
|
|
112
|
-
const isDedupeKey = pKey.startsWith(InternalKeySymbol);
|
|
113
|
-
if (!isDedupeKey && packed[pKey]) {
|
|
114
|
-
packed[pKey] = Array.isArray(packed[pKey]) ? packed[pKey] : [packed[pKey]];
|
|
115
|
-
packed[pKey].push(Object.values(packedObj)[0]);
|
|
116
|
-
} else {
|
|
117
|
-
packed[isDedupeKey ? pKey.split("-").slice(1).join("-") || pKey : pKey] = packedObj[pKey];
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
return packed;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function unpackToArray(input, options) {
|
|
124
|
-
const unpacked = [];
|
|
125
|
-
const kFn = options.resolveKeyData || ((ctx) => ctx.key);
|
|
126
|
-
const vFn = options.resolveValueData || ((ctx) => ctx.value);
|
|
127
|
-
for (const [k, v] of Object.entries(input)) {
|
|
128
|
-
unpacked.push(...(Array.isArray(v) ? v : [v]).map((i) => {
|
|
129
|
-
const ctx = { key: k, value: i };
|
|
130
|
-
const val = vFn(ctx);
|
|
131
|
-
if (typeof val === "object")
|
|
132
|
-
return unpackToArray(val, options);
|
|
133
|
-
if (Array.isArray(val))
|
|
134
|
-
return val;
|
|
135
|
-
return {
|
|
136
|
-
[typeof options.key === "function" ? options.key(ctx) : options.key]: kFn(ctx),
|
|
137
|
-
[typeof options.value === "function" ? options.value(ctx) : options.value]: val
|
|
138
|
-
};
|
|
139
|
-
}).flat());
|
|
140
|
-
}
|
|
141
|
-
return unpacked;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
function unpackToString(value, options) {
|
|
145
|
-
return Object.entries(value).map(([key, value2]) => {
|
|
146
|
-
if (typeof value2 === "object")
|
|
147
|
-
value2 = unpackToString(value2, options);
|
|
148
|
-
if (options.resolve) {
|
|
149
|
-
const resolved = options.resolve({ key, value: value2 });
|
|
150
|
-
if (typeof resolved !== "undefined")
|
|
151
|
-
return resolved;
|
|
152
|
-
}
|
|
153
|
-
if (typeof value2 === "number")
|
|
154
|
-
value2 = value2.toString();
|
|
155
|
-
if (typeof value2 === "string" && options.wrapValue) {
|
|
156
|
-
value2 = value2.replace(new RegExp(options.wrapValue, "g"), `\\${options.wrapValue}`);
|
|
157
|
-
value2 = `${options.wrapValue}${value2}${options.wrapValue}`;
|
|
158
|
-
}
|
|
159
|
-
return `${key}${options.keyValueSeparator || ""}${value2}`;
|
|
160
|
-
}).join(options.entrySeparator || "");
|
|
161
|
-
}
|
|
162
|
-
|
|
163
69
|
const p = (p2) => ({ keyValue: p2, metaKey: "property" });
|
|
164
70
|
const k = (p2) => ({ keyValue: p2 });
|
|
165
71
|
const MetaPackingSchema = {
|
|
@@ -275,7 +181,7 @@ function resolvePackedMetaObjectValue(value, key) {
|
|
|
275
181
|
const definition = MetaPackingSchema[key];
|
|
276
182
|
if (key === "refresh")
|
|
277
183
|
return `${value.seconds};url=${value.url}`;
|
|
278
|
-
return unpackToString(
|
|
184
|
+
return packrup.unpackToString(
|
|
279
185
|
changeKeyCasingDeep(value),
|
|
280
186
|
{
|
|
281
187
|
keyValueSeparator: "=",
|
|
@@ -343,7 +249,7 @@ function unpackMeta(input) {
|
|
|
343
249
|
extras.push(...typeof v === "string" ? unpackMeta({ [key]: v }) : handleObjectEntry(key, v));
|
|
344
250
|
}
|
|
345
251
|
}
|
|
346
|
-
const meta = unpackToArray(primitives, {
|
|
252
|
+
const meta = packrup.unpackToArray(primitives, {
|
|
347
253
|
key({ key }) {
|
|
348
254
|
return resolveMetaKeyType(key);
|
|
349
255
|
},
|
|
@@ -369,7 +275,7 @@ function unpackMeta(input) {
|
|
|
369
275
|
}
|
|
370
276
|
function packMeta(inputs) {
|
|
371
277
|
const mappedPackingSchema = Object.entries(MetaPackingSchema).map(([key, value]) => [key, value.keyValue]);
|
|
372
|
-
return packArray(inputs, {
|
|
278
|
+
return packrup.packArray(inputs, {
|
|
373
279
|
key: ["name", "property", "httpEquiv", "http-equiv", "charset"],
|
|
374
280
|
value: ["content", "charset"],
|
|
375
281
|
resolveKey(k2) {
|
|
@@ -534,6 +440,7 @@ function whitelistSafeInput(input) {
|
|
|
534
440
|
if (!tagValue)
|
|
535
441
|
return;
|
|
536
442
|
switch (key) {
|
|
443
|
+
// always safe
|
|
537
444
|
case "title":
|
|
538
445
|
case "titleTemplate":
|
|
539
446
|
case "templateParams":
|
|
@@ -547,6 +454,7 @@ function whitelistSafeInput(input) {
|
|
|
547
454
|
filtered[key][a] = tagValue[a];
|
|
548
455
|
});
|
|
549
456
|
break;
|
|
457
|
+
// meta is safe, except for http-equiv
|
|
550
458
|
case "meta":
|
|
551
459
|
if (Array.isArray(tagValue)) {
|
|
552
460
|
filtered[key] = tagValue.map((meta) => {
|
|
@@ -559,6 +467,7 @@ function whitelistSafeInput(input) {
|
|
|
559
467
|
}).filter((meta) => Object.keys(meta).length > 0);
|
|
560
468
|
}
|
|
561
469
|
break;
|
|
470
|
+
// link tags we don't allow stylesheets, scripts, preloading, prerendering, prefetching, etc
|
|
562
471
|
case "link":
|
|
563
472
|
if (Array.isArray(tagValue)) {
|
|
564
473
|
filtered[key] = tagValue.map((meta) => {
|
|
@@ -591,6 +500,7 @@ function whitelistSafeInput(input) {
|
|
|
591
500
|
}).filter((meta) => Object.keys(meta).length > 0);
|
|
592
501
|
}
|
|
593
502
|
break;
|
|
503
|
+
// we only allow JSON in scripts
|
|
594
504
|
case "script":
|
|
595
505
|
if (Array.isArray(tagValue)) {
|
|
596
506
|
filtered[key] = tagValue.map((script) => {
|
|
@@ -743,7 +653,7 @@ exports.TagEntityBits = TagEntityBits;
|
|
|
743
653
|
exports.TagsWithInnerContent = TagsWithInnerContent;
|
|
744
654
|
exports.UniqueTags = UniqueTags;
|
|
745
655
|
exports.ValidHeadTags = ValidHeadTags;
|
|
746
|
-
exports.asArray = asArray
|
|
656
|
+
exports.asArray = asArray;
|
|
747
657
|
exports.composableNames = composableNames;
|
|
748
658
|
exports.defineHeadPlugin = defineHeadPlugin;
|
|
749
659
|
exports.hashCode = hashCode;
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { unpackToString, unpackToArray, packArray } from 'packrup';
|
|
2
|
+
|
|
3
|
+
function asArray(value) {
|
|
2
4
|
return Array.isArray(value) ? value : [value];
|
|
3
5
|
}
|
|
4
6
|
|
|
@@ -62,102 +64,6 @@ function hashTag(tag) {
|
|
|
62
64
|
return hashCode(content);
|
|
63
65
|
}
|
|
64
66
|
|
|
65
|
-
function asArray(input) {
|
|
66
|
-
return Array.isArray(input) ? input : [input];
|
|
67
|
-
}
|
|
68
|
-
const InternalKeySymbol = "_$key";
|
|
69
|
-
function packObject(input, options) {
|
|
70
|
-
const keys = Object.keys(input);
|
|
71
|
-
let [k, v] = keys;
|
|
72
|
-
options = options || {};
|
|
73
|
-
options.key = options.key || k;
|
|
74
|
-
options.value = options.value || v;
|
|
75
|
-
options.resolveKey = options.resolveKey || ((k2) => k2);
|
|
76
|
-
const resolveKey = (index) => {
|
|
77
|
-
const arr = asArray(options[index]);
|
|
78
|
-
return arr.find((k2) => {
|
|
79
|
-
if (typeof k2 === "string" && k2.includes(".")) {
|
|
80
|
-
return k2;
|
|
81
|
-
}
|
|
82
|
-
return k2 && keys.includes(k2);
|
|
83
|
-
});
|
|
84
|
-
};
|
|
85
|
-
const resolveValue = (k2, input2) => {
|
|
86
|
-
if (k2.includes(".")) {
|
|
87
|
-
const paths = k2.split(".");
|
|
88
|
-
let val = input2;
|
|
89
|
-
for (const path of paths)
|
|
90
|
-
val = val[path];
|
|
91
|
-
return val;
|
|
92
|
-
}
|
|
93
|
-
return input2[k2];
|
|
94
|
-
};
|
|
95
|
-
k = resolveKey("key") || k;
|
|
96
|
-
v = resolveKey("value") || v;
|
|
97
|
-
const dedupeKeyPrefix = input.key ? `${InternalKeySymbol}${input.key}-` : "";
|
|
98
|
-
let keyValue = resolveValue(k, input);
|
|
99
|
-
keyValue = options.resolveKey(keyValue);
|
|
100
|
-
return {
|
|
101
|
-
[`${dedupeKeyPrefix}${keyValue}`]: resolveValue(v, input)
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function packArray(input, options) {
|
|
106
|
-
const packed = {};
|
|
107
|
-
for (const i of input) {
|
|
108
|
-
const packedObj = packObject(i, options);
|
|
109
|
-
const pKey = Object.keys(packedObj)[0];
|
|
110
|
-
const isDedupeKey = pKey.startsWith(InternalKeySymbol);
|
|
111
|
-
if (!isDedupeKey && packed[pKey]) {
|
|
112
|
-
packed[pKey] = Array.isArray(packed[pKey]) ? packed[pKey] : [packed[pKey]];
|
|
113
|
-
packed[pKey].push(Object.values(packedObj)[0]);
|
|
114
|
-
} else {
|
|
115
|
-
packed[isDedupeKey ? pKey.split("-").slice(1).join("-") || pKey : pKey] = packedObj[pKey];
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
return packed;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function unpackToArray(input, options) {
|
|
122
|
-
const unpacked = [];
|
|
123
|
-
const kFn = options.resolveKeyData || ((ctx) => ctx.key);
|
|
124
|
-
const vFn = options.resolveValueData || ((ctx) => ctx.value);
|
|
125
|
-
for (const [k, v] of Object.entries(input)) {
|
|
126
|
-
unpacked.push(...(Array.isArray(v) ? v : [v]).map((i) => {
|
|
127
|
-
const ctx = { key: k, value: i };
|
|
128
|
-
const val = vFn(ctx);
|
|
129
|
-
if (typeof val === "object")
|
|
130
|
-
return unpackToArray(val, options);
|
|
131
|
-
if (Array.isArray(val))
|
|
132
|
-
return val;
|
|
133
|
-
return {
|
|
134
|
-
[typeof options.key === "function" ? options.key(ctx) : options.key]: kFn(ctx),
|
|
135
|
-
[typeof options.value === "function" ? options.value(ctx) : options.value]: val
|
|
136
|
-
};
|
|
137
|
-
}).flat());
|
|
138
|
-
}
|
|
139
|
-
return unpacked;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function unpackToString(value, options) {
|
|
143
|
-
return Object.entries(value).map(([key, value2]) => {
|
|
144
|
-
if (typeof value2 === "object")
|
|
145
|
-
value2 = unpackToString(value2, options);
|
|
146
|
-
if (options.resolve) {
|
|
147
|
-
const resolved = options.resolve({ key, value: value2 });
|
|
148
|
-
if (typeof resolved !== "undefined")
|
|
149
|
-
return resolved;
|
|
150
|
-
}
|
|
151
|
-
if (typeof value2 === "number")
|
|
152
|
-
value2 = value2.toString();
|
|
153
|
-
if (typeof value2 === "string" && options.wrapValue) {
|
|
154
|
-
value2 = value2.replace(new RegExp(options.wrapValue, "g"), `\\${options.wrapValue}`);
|
|
155
|
-
value2 = `${options.wrapValue}${value2}${options.wrapValue}`;
|
|
156
|
-
}
|
|
157
|
-
return `${key}${options.keyValueSeparator || ""}${value2}`;
|
|
158
|
-
}).join(options.entrySeparator || "");
|
|
159
|
-
}
|
|
160
|
-
|
|
161
67
|
const p = (p2) => ({ keyValue: p2, metaKey: "property" });
|
|
162
68
|
const k = (p2) => ({ keyValue: p2 });
|
|
163
69
|
const MetaPackingSchema = {
|
|
@@ -532,6 +438,7 @@ function whitelistSafeInput(input) {
|
|
|
532
438
|
if (!tagValue)
|
|
533
439
|
return;
|
|
534
440
|
switch (key) {
|
|
441
|
+
// always safe
|
|
535
442
|
case "title":
|
|
536
443
|
case "titleTemplate":
|
|
537
444
|
case "templateParams":
|
|
@@ -545,6 +452,7 @@ function whitelistSafeInput(input) {
|
|
|
545
452
|
filtered[key][a] = tagValue[a];
|
|
546
453
|
});
|
|
547
454
|
break;
|
|
455
|
+
// meta is safe, except for http-equiv
|
|
548
456
|
case "meta":
|
|
549
457
|
if (Array.isArray(tagValue)) {
|
|
550
458
|
filtered[key] = tagValue.map((meta) => {
|
|
@@ -557,6 +465,7 @@ function whitelistSafeInput(input) {
|
|
|
557
465
|
}).filter((meta) => Object.keys(meta).length > 0);
|
|
558
466
|
}
|
|
559
467
|
break;
|
|
468
|
+
// link tags we don't allow stylesheets, scripts, preloading, prerendering, prefetching, etc
|
|
560
469
|
case "link":
|
|
561
470
|
if (Array.isArray(tagValue)) {
|
|
562
471
|
filtered[key] = tagValue.map((meta) => {
|
|
@@ -589,6 +498,7 @@ function whitelistSafeInput(input) {
|
|
|
589
498
|
}).filter((meta) => Object.keys(meta).length > 0);
|
|
590
499
|
}
|
|
591
500
|
break;
|
|
501
|
+
// we only allow JSON in scripts
|
|
592
502
|
case "script":
|
|
593
503
|
if (Array.isArray(tagValue)) {
|
|
594
504
|
filtered[key] = tagValue.map((script) => {
|
|
@@ -728,4 +638,4 @@ function resolveTitleTemplate(template, title) {
|
|
|
728
638
|
return template;
|
|
729
639
|
}
|
|
730
640
|
|
|
731
|
-
export { HasElementTags, IsBrowser, NetworkEvents, ScriptNetworkEvents, SelfClosingTags, SortModifiers, TAG_ALIASES, TAG_WEIGHTS, TagConfigKeys, TagEntityBits, TagsWithInnerContent, UniqueTags, ValidHeadTags, asArray
|
|
641
|
+
export { HasElementTags, IsBrowser, NetworkEvents, ScriptNetworkEvents, SelfClosingTags, SortModifiers, TAG_ALIASES, TAG_WEIGHTS, TagConfigKeys, TagEntityBits, TagsWithInnerContent, UniqueTags, ValidHeadTags, asArray, composableNames, defineHeadPlugin, hashCode, hashTag, normaliseEntryTags, normaliseProps, normaliseStyleClassProps, normaliseTag, packMeta, processTemplateParams, resolveMetaKeyType, resolveMetaKeyValue, resolvePackedMetaObjectValue, resolveTitleTemplate, tagDedupeKey, tagWeight, thenable, unpackMeta, whitelistSafeInput };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unhead/shared",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.11.
|
|
4
|
+
"version": "1.11.15",
|
|
5
5
|
"author": "Harlan Wilton <harlan@harlanzw.com>",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"funding": "https://github.com/sponsors/harlan-zw",
|
|
@@ -34,10 +34,8 @@
|
|
|
34
34
|
"dist"
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
"devDependencies": {
|
|
40
|
-
"packrup": "^0.1.2"
|
|
37
|
+
"packrup": "^0.1.2",
|
|
38
|
+
"@unhead/schema": "1.11.15"
|
|
41
39
|
},
|
|
42
40
|
"scripts": {
|
|
43
41
|
"build": "unbuild .",
|