@unhead/shared 1.6.1 → 1.6.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/index.cjs CHANGED
@@ -5,7 +5,7 @@ function asArray$1(value) {
5
5
  }
6
6
 
7
7
  const SelfClosingTags = ["meta", "link", "base"];
8
- const TagsWithInnerContent = ["title", "script", "style", "noscript"];
8
+ const TagsWithInnerContent = ["title", "titleTemplate", "script", "style", "noscript"];
9
9
  const HasElementTags = [
10
10
  "base",
11
11
  "meta",
@@ -28,7 +28,7 @@ const ValidHeadTags = [
28
28
  "noscript"
29
29
  ];
30
30
  const UniqueTags = ["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs", "templateParams"];
31
- const TagConfigKeys = ["tagPosition", "tagPriority", "tagDuplicateStrategy", "innerHTML", "textContent"];
31
+ const TagConfigKeys = ["tagPosition", "tagPriority", "tagDuplicateStrategy", "innerHTML", "textContent", "processTemplateParams"];
32
32
  const IsBrowser = typeof window !== "undefined";
33
33
  const composableNames = [
34
34
  "getActiveHead",
@@ -555,57 +555,40 @@ function whitelistSafeInput(input) {
555
555
  }
556
556
 
557
557
  async function normaliseTag(tagName, input, e) {
558
- const tag = { tag: tagName, props: {} };
559
- if (input instanceof Promise)
560
- input = await input;
561
- if (tagName === "templateParams") {
562
- tag.props = input;
563
- return tag;
564
- }
565
- if (["title", "titleTemplate"].includes(tagName)) {
566
- if (input && typeof input === "object") {
567
- tag.textContent = input.textContent;
568
- if (input.tagPriority)
569
- tag.tagPriority = input.tagPriority;
570
- } else {
571
- tag.textContent = input;
572
- }
573
- return tag;
574
- }
575
- if (typeof input === "string") {
576
- if (!["script", "noscript", "style"].includes(tagName))
577
- return false;
578
- if (tagName === "script" && (/^(https?:)?\/\//.test(input) || input.startsWith("/")))
579
- tag.props.src = input;
580
- else
581
- tag.innerHTML = input;
582
- return tag;
583
- }
584
- if (input.body) {
585
- input.tagPosition = "bodyClose";
586
- delete input.body;
587
- }
588
- if (input.children) {
589
- input.innerHTML = input.children;
590
- delete input.children;
591
- }
592
- tag.props = await normaliseProps({ ...input });
593
- Object.keys(tag.props).filter((k) => TagConfigKeys.includes(k)).forEach((k) => {
594
- if (!["innerHTML", "textContent"].includes(k) || TagsWithInnerContent.includes(tag.tag)) {
595
- tag[k] = tag.props[k];
596
- }
597
- delete tag.props[k];
598
- });
558
+ const tag = {
559
+ tag: tagName,
560
+ props: await normaliseProps(
561
+ // explicitly check for an object
562
+ // @ts-expect-error untyped
563
+ typeof input === "object" && typeof input !== "function" && !(input instanceof Promise) ? { ...input } : { [["script", "noscript", "style"].includes(tagName) ? "innerHTML" : "textContent"]: input },
564
+ ["templateParams", "titleTemplate"].includes(tagName)
565
+ )
566
+ };
599
567
  TagConfigKeys.forEach((k) => {
600
- if (!tag[k] && e[k]) {
601
- tag[k] = e[k];
568
+ const val = typeof tag.props[k] !== "undefined" ? tag.props[k] : e[k];
569
+ if (typeof val !== "undefined") {
570
+ if (!["innerHTML", "textContent"].includes(k) || TagsWithInnerContent.includes(tag.tag)) {
571
+ tag[k] = val;
572
+ }
573
+ delete tag.props[k];
602
574
  }
603
575
  });
604
- if (tag.tag === "script" && typeof tag.innerHTML === "object")
576
+ if (tag.props.body) {
577
+ tag.tagPosition = "bodyClose";
578
+ delete tag.props.body;
579
+ }
580
+ if (tag.props.children) {
581
+ tag.innerHTML = tag.props.children;
582
+ delete tag.props.children;
583
+ }
584
+ if (tag.tag === "script" && typeof tag.innerHTML === "object") {
605
585
  tag.innerHTML = JSON.stringify(tag.innerHTML);
606
- if (tag.props.content && Array.isArray(tag.props.content))
607
- return tag.props.content.map((v) => ({ ...tag, props: { ...tag.props, content: v } }));
608
- return tag;
586
+ tag.props.type = tag.props.type || "application/json";
587
+ } else if (tag.tag === "script" && tag.innerHTML && (/^(https?:)?\/\//.test(tag.innerHTML) || tag.innerHTML.startsWith("/"))) {
588
+ tag.props.src = tag.innerHTML;
589
+ delete tag.innerHTML;
590
+ }
591
+ return Array.isArray(tag.props.content) ? tag.props.content.map((v) => ({ ...tag, props: { ...tag.props, content: v } })) : tag;
609
592
  }
610
593
  function normaliseClassProp(v) {
611
594
  if (typeof v === "object" && !Array.isArray(v)) {
@@ -613,7 +596,7 @@ function normaliseClassProp(v) {
613
596
  }
614
597
  return (Array.isArray(v) ? v.join(" ") : v).split(" ").filter((c) => c.trim()).filter(Boolean).join(" ");
615
598
  }
616
- async function normaliseProps(props) {
599
+ async function normaliseProps(props, virtual) {
617
600
  for (const k of Object.keys(props)) {
618
601
  if (k === "class") {
619
602
  props[k] = normaliseClassProp(props[k]);
@@ -621,15 +604,17 @@ async function normaliseProps(props) {
621
604
  }
622
605
  if (props[k] instanceof Promise)
623
606
  props[k] = await props[k];
624
- const v = String(props[k]);
625
- const isDataKey = k.startsWith("data-");
626
- if (v === "true" || v === "") {
627
- props[k] = isDataKey ? "true" : true;
628
- } else if (!props[k]) {
629
- if (isDataKey && v === "false")
630
- props[k] = "false";
631
- else
632
- delete props[k];
607
+ if (!virtual && !TagConfigKeys.includes(k)) {
608
+ const v = String(props[k]);
609
+ const isDataKey = k.startsWith("data-");
610
+ if (v === "true" || v === "") {
611
+ props[k] = isDataKey ? "true" : true;
612
+ } else if (!props[k]) {
613
+ if (isDataKey && v === "false")
614
+ props[k] = "false";
615
+ else
616
+ delete props[k];
617
+ }
633
618
  }
634
619
  }
635
620
  return props;
package/dist/index.d.cts CHANGED
@@ -40,7 +40,7 @@ declare function whitelistSafeInput(input: Record<string, MaybeArray<Record<stri
40
40
 
41
41
  declare function normaliseTag<T extends HeadTag>(tagName: T['tag'], input: HeadTag['props'] | string, e: HeadEntry<T>): Promise<T | T[] | false>;
42
42
  declare function normaliseClassProp(v: Required<Required<Head>['htmlAttrs']['class']>): string;
43
- declare function normaliseProps<T extends HeadTag>(props: T['props']): Promise<T['props']>;
43
+ declare function normaliseProps<T extends HeadTag>(props: T['props'], virtual?: boolean): Promise<T['props']>;
44
44
  declare const TagEntityBits = 10;
45
45
  declare function normaliseEntryTags<T extends {} = Head>(e: HeadEntry<T>): Promise<HeadTag[]>;
46
46
 
package/dist/index.d.mts CHANGED
@@ -40,7 +40,7 @@ declare function whitelistSafeInput(input: Record<string, MaybeArray<Record<stri
40
40
 
41
41
  declare function normaliseTag<T extends HeadTag>(tagName: T['tag'], input: HeadTag['props'] | string, e: HeadEntry<T>): Promise<T | T[] | false>;
42
42
  declare function normaliseClassProp(v: Required<Required<Head>['htmlAttrs']['class']>): string;
43
- declare function normaliseProps<T extends HeadTag>(props: T['props']): Promise<T['props']>;
43
+ declare function normaliseProps<T extends HeadTag>(props: T['props'], virtual?: boolean): Promise<T['props']>;
44
44
  declare const TagEntityBits = 10;
45
45
  declare function normaliseEntryTags<T extends {} = Head>(e: HeadEntry<T>): Promise<HeadTag[]>;
46
46
 
package/dist/index.d.ts CHANGED
@@ -40,7 +40,7 @@ declare function whitelistSafeInput(input: Record<string, MaybeArray<Record<stri
40
40
 
41
41
  declare function normaliseTag<T extends HeadTag>(tagName: T['tag'], input: HeadTag['props'] | string, e: HeadEntry<T>): Promise<T | T[] | false>;
42
42
  declare function normaliseClassProp(v: Required<Required<Head>['htmlAttrs']['class']>): string;
43
- declare function normaliseProps<T extends HeadTag>(props: T['props']): Promise<T['props']>;
43
+ declare function normaliseProps<T extends HeadTag>(props: T['props'], virtual?: boolean): Promise<T['props']>;
44
44
  declare const TagEntityBits = 10;
45
45
  declare function normaliseEntryTags<T extends {} = Head>(e: HeadEntry<T>): Promise<HeadTag[]>;
46
46
 
package/dist/index.mjs CHANGED
@@ -3,7 +3,7 @@ function asArray$1(value) {
3
3
  }
4
4
 
5
5
  const SelfClosingTags = ["meta", "link", "base"];
6
- const TagsWithInnerContent = ["title", "script", "style", "noscript"];
6
+ const TagsWithInnerContent = ["title", "titleTemplate", "script", "style", "noscript"];
7
7
  const HasElementTags = [
8
8
  "base",
9
9
  "meta",
@@ -26,7 +26,7 @@ const ValidHeadTags = [
26
26
  "noscript"
27
27
  ];
28
28
  const UniqueTags = ["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs", "templateParams"];
29
- const TagConfigKeys = ["tagPosition", "tagPriority", "tagDuplicateStrategy", "innerHTML", "textContent"];
29
+ const TagConfigKeys = ["tagPosition", "tagPriority", "tagDuplicateStrategy", "innerHTML", "textContent", "processTemplateParams"];
30
30
  const IsBrowser = typeof window !== "undefined";
31
31
  const composableNames = [
32
32
  "getActiveHead",
@@ -553,57 +553,40 @@ function whitelistSafeInput(input) {
553
553
  }
554
554
 
555
555
  async function normaliseTag(tagName, input, e) {
556
- const tag = { tag: tagName, props: {} };
557
- if (input instanceof Promise)
558
- input = await input;
559
- if (tagName === "templateParams") {
560
- tag.props = input;
561
- return tag;
562
- }
563
- if (["title", "titleTemplate"].includes(tagName)) {
564
- if (input && typeof input === "object") {
565
- tag.textContent = input.textContent;
566
- if (input.tagPriority)
567
- tag.tagPriority = input.tagPriority;
568
- } else {
569
- tag.textContent = input;
570
- }
571
- return tag;
572
- }
573
- if (typeof input === "string") {
574
- if (!["script", "noscript", "style"].includes(tagName))
575
- return false;
576
- if (tagName === "script" && (/^(https?:)?\/\//.test(input) || input.startsWith("/")))
577
- tag.props.src = input;
578
- else
579
- tag.innerHTML = input;
580
- return tag;
581
- }
582
- if (input.body) {
583
- input.tagPosition = "bodyClose";
584
- delete input.body;
585
- }
586
- if (input.children) {
587
- input.innerHTML = input.children;
588
- delete input.children;
589
- }
590
- tag.props = await normaliseProps({ ...input });
591
- Object.keys(tag.props).filter((k) => TagConfigKeys.includes(k)).forEach((k) => {
592
- if (!["innerHTML", "textContent"].includes(k) || TagsWithInnerContent.includes(tag.tag)) {
593
- tag[k] = tag.props[k];
594
- }
595
- delete tag.props[k];
596
- });
556
+ const tag = {
557
+ tag: tagName,
558
+ props: await normaliseProps(
559
+ // explicitly check for an object
560
+ // @ts-expect-error untyped
561
+ typeof input === "object" && typeof input !== "function" && !(input instanceof Promise) ? { ...input } : { [["script", "noscript", "style"].includes(tagName) ? "innerHTML" : "textContent"]: input },
562
+ ["templateParams", "titleTemplate"].includes(tagName)
563
+ )
564
+ };
597
565
  TagConfigKeys.forEach((k) => {
598
- if (!tag[k] && e[k]) {
599
- tag[k] = e[k];
566
+ const val = typeof tag.props[k] !== "undefined" ? tag.props[k] : e[k];
567
+ if (typeof val !== "undefined") {
568
+ if (!["innerHTML", "textContent"].includes(k) || TagsWithInnerContent.includes(tag.tag)) {
569
+ tag[k] = val;
570
+ }
571
+ delete tag.props[k];
600
572
  }
601
573
  });
602
- if (tag.tag === "script" && typeof tag.innerHTML === "object")
574
+ if (tag.props.body) {
575
+ tag.tagPosition = "bodyClose";
576
+ delete tag.props.body;
577
+ }
578
+ if (tag.props.children) {
579
+ tag.innerHTML = tag.props.children;
580
+ delete tag.props.children;
581
+ }
582
+ if (tag.tag === "script" && typeof tag.innerHTML === "object") {
603
583
  tag.innerHTML = JSON.stringify(tag.innerHTML);
604
- if (tag.props.content && Array.isArray(tag.props.content))
605
- return tag.props.content.map((v) => ({ ...tag, props: { ...tag.props, content: v } }));
606
- return tag;
584
+ tag.props.type = tag.props.type || "application/json";
585
+ } else if (tag.tag === "script" && tag.innerHTML && (/^(https?:)?\/\//.test(tag.innerHTML) || tag.innerHTML.startsWith("/"))) {
586
+ tag.props.src = tag.innerHTML;
587
+ delete tag.innerHTML;
588
+ }
589
+ return Array.isArray(tag.props.content) ? tag.props.content.map((v) => ({ ...tag, props: { ...tag.props, content: v } })) : tag;
607
590
  }
608
591
  function normaliseClassProp(v) {
609
592
  if (typeof v === "object" && !Array.isArray(v)) {
@@ -611,7 +594,7 @@ function normaliseClassProp(v) {
611
594
  }
612
595
  return (Array.isArray(v) ? v.join(" ") : v).split(" ").filter((c) => c.trim()).filter(Boolean).join(" ");
613
596
  }
614
- async function normaliseProps(props) {
597
+ async function normaliseProps(props, virtual) {
615
598
  for (const k of Object.keys(props)) {
616
599
  if (k === "class") {
617
600
  props[k] = normaliseClassProp(props[k]);
@@ -619,15 +602,17 @@ async function normaliseProps(props) {
619
602
  }
620
603
  if (props[k] instanceof Promise)
621
604
  props[k] = await props[k];
622
- const v = String(props[k]);
623
- const isDataKey = k.startsWith("data-");
624
- if (v === "true" || v === "") {
625
- props[k] = isDataKey ? "true" : true;
626
- } else if (!props[k]) {
627
- if (isDataKey && v === "false")
628
- props[k] = "false";
629
- else
630
- delete props[k];
605
+ if (!virtual && !TagConfigKeys.includes(k)) {
606
+ const v = String(props[k]);
607
+ const isDataKey = k.startsWith("data-");
608
+ if (v === "true" || v === "") {
609
+ props[k] = isDataKey ? "true" : true;
610
+ } else if (!props[k]) {
611
+ if (isDataKey && v === "false")
612
+ props[k] = "false";
613
+ else
614
+ delete props[k];
615
+ }
631
616
  }
632
617
  }
633
618
  return props;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@unhead/shared",
3
3
  "type": "module",
4
- "version": "1.6.1",
4
+ "version": "1.6.2",
5
5
  "author": "Harlan Wilton <harlan@harlanzw.com>",
6
6
  "license": "MIT",
7
7
  "funding": "https://github.com/sponsors/harlan-zw",
@@ -34,7 +34,7 @@
34
34
  "dist"
35
35
  ],
36
36
  "dependencies": {
37
- "@unhead/schema": "1.6.1"
37
+ "@unhead/schema": "1.6.2"
38
38
  },
39
39
  "devDependencies": {
40
40
  "packrup": "^0.1.0"