@unhead/shared 1.0.22

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/README.md ADDED
@@ -0,0 +1,16 @@
1
+ # `@unhead/schema`
2
+
3
+ Typescript definitions for document `<head>`.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install --save-dev @unhead/schema
9
+
10
+ # Using yarn
11
+ yarn add --dev @unhead/schema
12
+ ```
13
+
14
+ ## Types
15
+
16
+ See [head.ts](./src/head.ts) for the full list of types.
package/dist/index.cjs ADDED
@@ -0,0 +1,130 @@
1
+ 'use strict';
2
+
3
+ function asArray(value) {
4
+ return Array.isArray(value) ? value : [value];
5
+ }
6
+
7
+ const SelfClosingTags = ["meta", "link", "base"];
8
+ const TagsWithInnerContent = ["title", "script", "style", "noscript"];
9
+ const HasElementTags = [
10
+ "base",
11
+ "meta",
12
+ "link",
13
+ "style",
14
+ "script",
15
+ "noscript"
16
+ ];
17
+ const ValidHeadTags = [
18
+ "title",
19
+ "titleTemplate",
20
+ "base",
21
+ "htmlAttrs",
22
+ "bodyAttrs",
23
+ "meta",
24
+ "link",
25
+ "style",
26
+ "script",
27
+ "noscript"
28
+ ];
29
+ const UniqueTags = ["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs"];
30
+ const TagConfigKeys = ["tagPosition", "tagPriority", "tagDuplicateStrategy"];
31
+
32
+ function tagDedupeKey(tag, fn) {
33
+ const { props, tag: tagName } = tag;
34
+ if (UniqueTags.includes(tagName))
35
+ return tagName;
36
+ if (tagName === "link" && props.rel === "canonical")
37
+ return "canonical";
38
+ if (props.charset)
39
+ return "charset";
40
+ const name = ["id"];
41
+ if (tagName === "meta")
42
+ name.push(...["name", "property", "http-equiv"]);
43
+ for (const n of name) {
44
+ if (typeof props[n] !== "undefined") {
45
+ const val = String(props[n]);
46
+ if (fn && !fn(val))
47
+ return false;
48
+ return `${tagName}:${n}:${val}`;
49
+ }
50
+ }
51
+ return false;
52
+ }
53
+ const DedupesTagsPlugin = (options) => {
54
+ options = options || {};
55
+ const dedupeKeys = options.dedupeKeys || ["hid", "vmid", "key"];
56
+ return defineHeadPlugin({
57
+ hooks: {
58
+ "tag:normalise": function({ tag }) {
59
+ dedupeKeys.forEach((key) => {
60
+ if (tag.props[key]) {
61
+ tag.key = tag.props[key];
62
+ delete tag.props[key];
63
+ }
64
+ });
65
+ const dedupe = tag.key ? `${tag.tag}:${tag.key}` : tagDedupeKey(tag);
66
+ if (dedupe)
67
+ tag._d = dedupe;
68
+ },
69
+ "tags:resolve": function(ctx) {
70
+ const deduping = {};
71
+ ctx.tags.forEach((tag) => {
72
+ let dedupeKey = tag._d || tag._p;
73
+ const dupedTag = deduping[dedupeKey];
74
+ if (dupedTag) {
75
+ let strategy = tag?.tagDuplicateStrategy;
76
+ if (!strategy && (tag.tag === "htmlAttrs" || tag.tag === "bodyAttrs"))
77
+ strategy = "merge";
78
+ if (strategy === "merge") {
79
+ const oldProps = dupedTag.props;
80
+ ["class", "style"].forEach((key) => {
81
+ if (tag.props[key] && oldProps[key]) {
82
+ if (key === "style" && !oldProps[key].endsWith(";"))
83
+ oldProps[key] += ";";
84
+ tag.props[key] = `${oldProps[key]} ${tag.props[key]}`;
85
+ }
86
+ });
87
+ deduping[dedupeKey].props = {
88
+ ...oldProps,
89
+ ...tag.props
90
+ };
91
+ return;
92
+ } else if (tag._e === dupedTag._e) {
93
+ dedupeKey = tag._d = `${dedupeKey}:${tag._p}`;
94
+ }
95
+ const propCount = Object.keys(tag.props).length;
96
+ if ((propCount === 0 || propCount === 1 && typeof tag.props["data-h-key"] !== "undefined") && !tag.children) {
97
+ delete deduping[dedupeKey];
98
+ return;
99
+ }
100
+ }
101
+ deduping[dedupeKey] = tag;
102
+ });
103
+ ctx.tags = Object.values(deduping);
104
+ }
105
+ }
106
+ });
107
+ };
108
+
109
+ function defineHeadPlugin(plugin) {
110
+ return plugin;
111
+ }
112
+
113
+ function hashCode(s) {
114
+ let h = 9;
115
+ for (let i = 0; i < s.length; )
116
+ h = Math.imul(h ^ s.charCodeAt(i++), 9 ** 9);
117
+ return ((h ^ h >>> 9) + 65536).toString(16).substring(1, 8).toLowerCase();
118
+ }
119
+
120
+ exports.DedupesTagsPlugin = DedupesTagsPlugin;
121
+ exports.HasElementTags = HasElementTags;
122
+ exports.SelfClosingTags = SelfClosingTags;
123
+ exports.TagConfigKeys = TagConfigKeys;
124
+ exports.TagsWithInnerContent = TagsWithInnerContent;
125
+ exports.UniqueTags = UniqueTags;
126
+ exports.ValidHeadTags = ValidHeadTags;
127
+ exports.asArray = asArray;
128
+ exports.defineHeadPlugin = defineHeadPlugin;
129
+ exports.hashCode = hashCode;
130
+ exports.tagDedupeKey = tagDedupeKey;
@@ -0,0 +1,25 @@
1
+ import * as _unhead_schema from '@unhead/schema';
2
+ import { HeadPlugin } from '@unhead/schema';
3
+ import { HeadTag } from '@unhead/schema/dist';
4
+
5
+ type Arrayable<T> = T | Array<T>;
6
+ declare function asArray<T>(value: Arrayable<T>): T[];
7
+
8
+ declare const SelfClosingTags: string[];
9
+ declare const TagsWithInnerContent: string[];
10
+ declare const HasElementTags: string[];
11
+ declare const ValidHeadTags: string[];
12
+ declare const UniqueTags: string[];
13
+ declare const TagConfigKeys: string[];
14
+
15
+ interface DedupesTagsPluginOptions {
16
+ dedupeKeys?: string[];
17
+ }
18
+ declare function tagDedupeKey<T extends HeadTag>(tag: T, fn?: (key: string) => boolean): string | false;
19
+ declare const DedupesTagsPlugin: (options?: DedupesTagsPluginOptions) => _unhead_schema.HeadPlugin;
20
+
21
+ declare function defineHeadPlugin(plugin: HeadPlugin): HeadPlugin;
22
+
23
+ declare function hashCode(s: string): string;
24
+
25
+ export { Arrayable, DedupesTagsPlugin, DedupesTagsPluginOptions, HasElementTags, SelfClosingTags, TagConfigKeys, TagsWithInnerContent, UniqueTags, ValidHeadTags, asArray, defineHeadPlugin, hashCode, tagDedupeKey };
package/dist/index.mjs ADDED
@@ -0,0 +1,118 @@
1
+ function asArray(value) {
2
+ return Array.isArray(value) ? value : [value];
3
+ }
4
+
5
+ const SelfClosingTags = ["meta", "link", "base"];
6
+ const TagsWithInnerContent = ["title", "script", "style", "noscript"];
7
+ const HasElementTags = [
8
+ "base",
9
+ "meta",
10
+ "link",
11
+ "style",
12
+ "script",
13
+ "noscript"
14
+ ];
15
+ const ValidHeadTags = [
16
+ "title",
17
+ "titleTemplate",
18
+ "base",
19
+ "htmlAttrs",
20
+ "bodyAttrs",
21
+ "meta",
22
+ "link",
23
+ "style",
24
+ "script",
25
+ "noscript"
26
+ ];
27
+ const UniqueTags = ["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs"];
28
+ const TagConfigKeys = ["tagPosition", "tagPriority", "tagDuplicateStrategy"];
29
+
30
+ function tagDedupeKey(tag, fn) {
31
+ const { props, tag: tagName } = tag;
32
+ if (UniqueTags.includes(tagName))
33
+ return tagName;
34
+ if (tagName === "link" && props.rel === "canonical")
35
+ return "canonical";
36
+ if (props.charset)
37
+ return "charset";
38
+ const name = ["id"];
39
+ if (tagName === "meta")
40
+ name.push(...["name", "property", "http-equiv"]);
41
+ for (const n of name) {
42
+ if (typeof props[n] !== "undefined") {
43
+ const val = String(props[n]);
44
+ if (fn && !fn(val))
45
+ return false;
46
+ return `${tagName}:${n}:${val}`;
47
+ }
48
+ }
49
+ return false;
50
+ }
51
+ const DedupesTagsPlugin = (options) => {
52
+ options = options || {};
53
+ const dedupeKeys = options.dedupeKeys || ["hid", "vmid", "key"];
54
+ return defineHeadPlugin({
55
+ hooks: {
56
+ "tag:normalise": function({ tag }) {
57
+ dedupeKeys.forEach((key) => {
58
+ if (tag.props[key]) {
59
+ tag.key = tag.props[key];
60
+ delete tag.props[key];
61
+ }
62
+ });
63
+ const dedupe = tag.key ? `${tag.tag}:${tag.key}` : tagDedupeKey(tag);
64
+ if (dedupe)
65
+ tag._d = dedupe;
66
+ },
67
+ "tags:resolve": function(ctx) {
68
+ const deduping = {};
69
+ ctx.tags.forEach((tag) => {
70
+ let dedupeKey = tag._d || tag._p;
71
+ const dupedTag = deduping[dedupeKey];
72
+ if (dupedTag) {
73
+ let strategy = tag?.tagDuplicateStrategy;
74
+ if (!strategy && (tag.tag === "htmlAttrs" || tag.tag === "bodyAttrs"))
75
+ strategy = "merge";
76
+ if (strategy === "merge") {
77
+ const oldProps = dupedTag.props;
78
+ ["class", "style"].forEach((key) => {
79
+ if (tag.props[key] && oldProps[key]) {
80
+ if (key === "style" && !oldProps[key].endsWith(";"))
81
+ oldProps[key] += ";";
82
+ tag.props[key] = `${oldProps[key]} ${tag.props[key]}`;
83
+ }
84
+ });
85
+ deduping[dedupeKey].props = {
86
+ ...oldProps,
87
+ ...tag.props
88
+ };
89
+ return;
90
+ } else if (tag._e === dupedTag._e) {
91
+ dedupeKey = tag._d = `${dedupeKey}:${tag._p}`;
92
+ }
93
+ const propCount = Object.keys(tag.props).length;
94
+ if ((propCount === 0 || propCount === 1 && typeof tag.props["data-h-key"] !== "undefined") && !tag.children) {
95
+ delete deduping[dedupeKey];
96
+ return;
97
+ }
98
+ }
99
+ deduping[dedupeKey] = tag;
100
+ });
101
+ ctx.tags = Object.values(deduping);
102
+ }
103
+ }
104
+ });
105
+ };
106
+
107
+ function defineHeadPlugin(plugin) {
108
+ return plugin;
109
+ }
110
+
111
+ function hashCode(s) {
112
+ let h = 9;
113
+ for (let i = 0; i < s.length; )
114
+ h = Math.imul(h ^ s.charCodeAt(i++), 9 ** 9);
115
+ return ((h ^ h >>> 9) + 65536).toString(16).substring(1, 8).toLowerCase();
116
+ }
117
+
118
+ export { DedupesTagsPlugin, HasElementTags, SelfClosingTags, TagConfigKeys, TagsWithInnerContent, UniqueTags, ValidHeadTags, asArray, defineHeadPlugin, hashCode, tagDedupeKey };
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@unhead/shared",
3
+ "type": "module",
4
+ "version": "1.0.22",
5
+ "packageManager": "pnpm@7.26.3",
6
+ "author": "Harlan Wilton <harlan@harlanzw.com>",
7
+ "license": "MIT",
8
+ "funding": "https://github.com/sponsors/harlan-zw",
9
+ "homepage": "https://unhead.harlanzw.com",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/unjs/unhead.git",
13
+ "directory": "packages/schema"
14
+ },
15
+ "bugs": {
16
+ "url": "https://github.com/unjs/unhead/issues"
17
+ },
18
+ "keywords": [
19
+ "head",
20
+ "meta tags",
21
+ "types"
22
+ ],
23
+ "sideEffects": false,
24
+ "exports": {
25
+ ".": {
26
+ "types": "./dist/index.d.ts",
27
+ "require": "./dist/index.cjs",
28
+ "import": "./dist/index.mjs"
29
+ }
30
+ },
31
+ "main": "dist/index.cjs",
32
+ "module": "dist/index.mjs",
33
+ "types": "dist/index.d.ts",
34
+ "files": [
35
+ "dist"
36
+ ],
37
+ "dependencies": {
38
+ "@unhead/schema": "1.0.22"
39
+ },
40
+ "scripts": {
41
+ "build": "unbuild .",
42
+ "stub": "unbuild . --stub"
43
+ }
44
+ }