unhead 3.0.4 → 3.1.0

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.
Files changed (53) hide show
  1. package/dist/client.d.mts +5 -5
  2. package/dist/client.d.ts +5 -5
  3. package/dist/index.d.mts +5 -5
  4. package/dist/index.d.ts +5 -5
  5. package/dist/legacy.d.mts +3 -3
  6. package/dist/legacy.d.ts +3 -3
  7. package/dist/parser.d.mts +1 -1
  8. package/dist/parser.d.ts +1 -1
  9. package/dist/plugins.d.mts +6 -33
  10. package/dist/plugins.d.ts +6 -33
  11. package/dist/plugins.mjs +35 -199
  12. package/dist/scripts.d.mts +4 -4
  13. package/dist/scripts.d.ts +4 -4
  14. package/dist/server.d.mts +4 -4
  15. package/dist/server.d.ts +4 -4
  16. package/dist/shared/{unhead.CHsGwxB0.d.ts → unhead.-D8hRpkn.d.ts} +2 -2
  17. package/dist/shared/{unhead.BfINO8Du.d.mts → unhead.B2jfOxG1.d.mts} +2 -2
  18. package/dist/shared/{unhead.D91IvQ_J.d.mts → unhead.B7bBMqva.d.mts} +1 -1
  19. package/dist/shared/{unhead.DCXRrsx_.d.ts → unhead.BRwJvCZb.d.ts} +2 -2
  20. package/dist/shared/{unhead.LatFr5s0.d.mts → unhead.BX9134DF.d.mts} +1 -1
  21. package/dist/shared/{unhead.m4TuRTvV.d.mts → unhead.BoZ-Ul8T.d.mts} +1 -1
  22. package/dist/shared/{unhead.DvqMLXpO.d.mts → unhead.ClE7lB2Z.d.mts} +1 -1
  23. package/dist/shared/{unhead.DoIxTwSF.d.ts → unhead.CqVawd25.d.ts} +1 -1
  24. package/dist/shared/{unhead.Bbk6Q9rK.d.mts → unhead.Cv5yrrUd.d.mts} +2 -2
  25. package/dist/shared/{unhead.CGloe9Qc.d.mts → unhead.Dc5Pn4qI.d.mts} +2 -2
  26. package/dist/shared/{unhead.9aHQrEvB.d.ts → unhead.DdarjSpi.d.ts} +2 -2
  27. package/dist/shared/{unhead.BcynQ3qJ.d.mts → unhead.DeoGMp34.d.mts} +1 -1
  28. package/dist/shared/{unhead.BcynQ3qJ.d.ts → unhead.DeoGMp34.d.ts} +1 -1
  29. package/dist/shared/unhead.Dl_lRDXb.d.mts +38 -0
  30. package/dist/shared/unhead.Dl_lRDXb.d.ts +38 -0
  31. package/dist/shared/{unhead.Ogog_XUX.d.ts → unhead.cXt2Dgt5.d.ts} +1 -1
  32. package/dist/shared/unhead.ebqUBTt1.mjs +513 -0
  33. package/dist/shared/{unhead.BmdY3z1V.d.ts → unhead.gui9LmZS.d.ts} +1 -1
  34. package/dist/shared/{unhead.CvqH1vcy.d.ts → unhead.q49lHHFN.d.ts} +1 -1
  35. package/dist/stream/client.d.mts +24 -5
  36. package/dist/stream/client.d.ts +24 -5
  37. package/dist/stream/server.d.mts +9 -6
  38. package/dist/stream/server.d.ts +9 -6
  39. package/dist/stream/server.mjs +15 -4
  40. package/dist/stream/unplugin.d.mts +81 -0
  41. package/dist/stream/unplugin.d.ts +81 -0
  42. package/dist/stream/unplugin.mjs +166 -0
  43. package/dist/stream/vite.d.mts +19 -27
  44. package/dist/stream/vite.d.ts +19 -27
  45. package/dist/stream/vite.mjs +6 -78
  46. package/dist/types.d.mts +6 -6
  47. package/dist/types.d.ts +6 -6
  48. package/dist/utils.d.mts +2 -2
  49. package/dist/utils.d.ts +2 -2
  50. package/dist/validate.d.mts +236 -0
  51. package/dist/validate.d.ts +236 -0
  52. package/dist/validate.mjs +49 -0
  53. package/package.json +20 -4
package/dist/client.d.mts CHANGED
@@ -1,9 +1,9 @@
1
- export { C as ClientUnhead, c as createHead } from './shared/unhead.Bbk6Q9rK.mjs';
2
- import { R as RenderDomHeadOptions } from './shared/unhead.D91IvQ_J.mjs';
3
- import { p as HeadRenderer, U as Unhead } from './shared/unhead.m4TuRTvV.mjs';
4
- export { c as CreateClientHeadOptions } from './shared/unhead.m4TuRTvV.mjs';
1
+ export { C as ClientUnhead, c as createHead } from './shared/unhead.Cv5yrrUd.mjs';
2
+ import { R as RenderDomHeadOptions } from './shared/unhead.B7bBMqva.mjs';
3
+ import { p as HeadRenderer, U as Unhead } from './shared/unhead.BoZ-Ul8T.mjs';
4
+ export { c as CreateClientHeadOptions } from './shared/unhead.BoZ-Ul8T.mjs';
5
5
  import 'hookable';
6
- import './shared/unhead.BcynQ3qJ.mjs';
6
+ import './shared/unhead.DeoGMp34.mjs';
7
7
 
8
8
  declare function createDomRenderer(options?: RenderDomHeadOptions): HeadRenderer<boolean>;
9
9
 
package/dist/client.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- export { C as ClientUnhead, c as createHead } from './shared/unhead.CHsGwxB0.js';
2
- import { R as RenderDomHeadOptions } from './shared/unhead.Ogog_XUX.js';
3
- import { p as HeadRenderer, U as Unhead } from './shared/unhead.BmdY3z1V.js';
4
- export { c as CreateClientHeadOptions } from './shared/unhead.BmdY3z1V.js';
1
+ export { C as ClientUnhead, c as createHead } from './shared/unhead.-D8hRpkn.js';
2
+ import { R as RenderDomHeadOptions } from './shared/unhead.cXt2Dgt5.js';
3
+ import { p as HeadRenderer, U as Unhead } from './shared/unhead.gui9LmZS.js';
4
+ export { c as CreateClientHeadOptions } from './shared/unhead.gui9LmZS.js';
5
5
  import 'hookable';
6
- import './shared/unhead.BcynQ3qJ.js';
6
+ import './shared/unhead.DeoGMp34.js';
7
7
 
8
8
  declare function createDomRenderer(options?: RenderDomHeadOptions): HeadRenderer<boolean>;
9
9
 
package/dist/index.d.mts CHANGED
@@ -1,8 +1,8 @@
1
- import { U as Unhead, k as HeadEntryOptions, A as ActiveHeadEntry } from './shared/unhead.m4TuRTvV.mjs';
2
- import { at as ResolvableHead, b1 as UseSeoMetaInput, J as InferLink, U as Link, K as InferScript, aI as Script } from './shared/unhead.BcynQ3qJ.mjs';
3
- import { H as HeadSafe } from './shared/unhead.LatFr5s0.mjs';
4
- export { c as createUnhead } from './shared/unhead.CGloe9Qc.mjs';
5
- export { u as useScript } from './shared/unhead.DvqMLXpO.mjs';
1
+ import { U as Unhead, k as HeadEntryOptions, A as ActiveHeadEntry } from './shared/unhead.BoZ-Ul8T.mjs';
2
+ import { aw as ResolvableHead, b5 as UseSeoMetaInput, M as InferLink, X as Link, N as InferScript, aL as Script } from './shared/unhead.DeoGMp34.mjs';
3
+ import { H as HeadSafe } from './shared/unhead.BX9134DF.mjs';
4
+ export { c as createUnhead } from './shared/unhead.Dc5Pn4qI.mjs';
5
+ export { u as useScript } from './shared/unhead.ClE7lB2Z.mjs';
6
6
  import 'hookable';
7
7
 
8
8
  declare function useHead<T extends Unhead<any>, I = ResolvableHead>(unhead: T, input?: ResolvableHead, options?: HeadEntryOptions): ActiveHeadEntry<I>;
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { U as Unhead, k as HeadEntryOptions, A as ActiveHeadEntry } from './shared/unhead.BmdY3z1V.js';
2
- import { at as ResolvableHead, b1 as UseSeoMetaInput, J as InferLink, U as Link, K as InferScript, aI as Script } from './shared/unhead.BcynQ3qJ.js';
3
- import { H as HeadSafe } from './shared/unhead.CvqH1vcy.js';
4
- export { c as createUnhead } from './shared/unhead.DCXRrsx_.js';
5
- export { u as useScript } from './shared/unhead.DoIxTwSF.js';
1
+ import { U as Unhead, k as HeadEntryOptions, A as ActiveHeadEntry } from './shared/unhead.gui9LmZS.js';
2
+ import { aw as ResolvableHead, b5 as UseSeoMetaInput, M as InferLink, X as Link, N as InferScript, aL as Script } from './shared/unhead.DeoGMp34.js';
3
+ import { H as HeadSafe } from './shared/unhead.q49lHHFN.js';
4
+ export { c as createUnhead } from './shared/unhead.BRwJvCZb.js';
5
+ export { u as useScript } from './shared/unhead.CqVawd25.js';
6
6
  import 'hookable';
7
7
 
8
8
  declare function useHead<T extends Unhead<any>, I = ResolvableHead>(unhead: T, input?: ResolvableHead, options?: HeadEntryOptions): ActiveHeadEntry<I>;
package/dist/legacy.d.mts CHANGED
@@ -1,6 +1,6 @@
1
- import { c as createUnhead } from './shared/unhead.CGloe9Qc.mjs';
2
- import { n as HeadPluginInput, U as Unhead, c as CreateClientHeadOptions, e as CreateServerHeadOptions } from './shared/unhead.m4TuRTvV.mjs';
3
- import { at as ResolvableHead } from './shared/unhead.BcynQ3qJ.mjs';
1
+ import { c as createUnhead } from './shared/unhead.Dc5Pn4qI.mjs';
2
+ import { n as HeadPluginInput, U as Unhead, c as CreateClientHeadOptions, e as CreateServerHeadOptions } from './shared/unhead.BoZ-Ul8T.mjs';
3
+ import { aw as ResolvableHead } from './shared/unhead.DeoGMp34.mjs';
4
4
  import 'hookable';
5
5
 
6
6
  /**
package/dist/legacy.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { c as createUnhead } from './shared/unhead.DCXRrsx_.js';
2
- import { n as HeadPluginInput, U as Unhead, c as CreateClientHeadOptions, e as CreateServerHeadOptions } from './shared/unhead.BmdY3z1V.js';
3
- import { at as ResolvableHead } from './shared/unhead.BcynQ3qJ.js';
1
+ import { c as createUnhead } from './shared/unhead.BRwJvCZb.js';
2
+ import { n as HeadPluginInput, U as Unhead, c as CreateClientHeadOptions, e as CreateServerHeadOptions } from './shared/unhead.gui9LmZS.js';
3
+ import { aw as ResolvableHead } from './shared/unhead.DeoGMp34.js';
4
4
  import 'hookable';
5
5
 
6
6
  /**
package/dist/parser.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { aM as SerializableHead } from './shared/unhead.BcynQ3qJ.mjs';
1
+ import { aP as SerializableHead } from './shared/unhead.DeoGMp34.mjs';
2
2
 
3
3
  declare const TagIdMap: {
4
4
  readonly html: 0;
package/dist/parser.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { aM as SerializableHead } from './shared/unhead.BcynQ3qJ.js';
1
+ import { aP as SerializableHead } from './shared/unhead.DeoGMp34.js';
2
2
 
3
3
  declare const TagIdMap: {
4
4
  readonly html: 0;
@@ -1,5 +1,7 @@
1
- import { n as HeadPluginInput, U as Unhead, o as HeadPluginOptions } from './shared/unhead.m4TuRTvV.mjs';
2
- import { t as HeadTag } from './shared/unhead.BcynQ3qJ.mjs';
1
+ import { n as HeadPluginInput, U as Unhead, o as HeadPluginOptions } from './shared/unhead.BoZ-Ul8T.mjs';
2
+ import { V as ValidationRuleId, R as RulesConfig } from './shared/unhead.Dl_lRDXb.mjs';
3
+ export { a as RuleConfig, b as RuleSeverity, c as ValidationRuleOptions } from './shared/unhead.Dl_lRDXb.mjs';
4
+ import { v as HeadTag } from './shared/unhead.DeoGMp34.mjs';
3
5
  import 'hookable';
4
6
 
5
7
  declare const AliasSortingPlugin: HeadPluginInput;
@@ -115,35 +117,6 @@ declare const SafeInputPlugin: HeadPluginInput;
115
117
 
116
118
  declare const TemplateParamsPlugin: HeadPluginInput;
117
119
 
118
- type RuleSeverity = 'warn' | 'info' | 'off';
119
- type ValidationRuleId = 'canonical-og-url-mismatch' | 'charset-not-early' | 'defer-on-module-script' | 'deprecated-option-mode' | 'deprecated-prop-body' | 'deprecated-prop-children' | 'deprecated-prop-hid-vmid' | 'duplicate-resource-hint' | 'empty-meta-content' | 'empty-title' | 'html-in-title' | 'inline-script-size' | 'inline-style-size' | 'meta-beyond-1mb' | 'missing-alias-sorting-plugin' | 'missing-description' | 'missing-template-params-plugin' | 'missing-title' | 'non-absolute-canonical' | 'non-absolute-og-url' | 'og-image-missing-dimensions' | 'og-missing-description' | 'og-missing-title' | 'possible-typo' | 'preconnect-missing-crossorigin' | 'prefetch-preload-conflict' | 'preload-async-defer-conflict' | 'preload-fetchpriority-conflict' | 'preload-font-crossorigin' | 'preload-missing-as' | 'preload-not-modulepreload' | 'redundant-dns-prefetch' | 'render-blocking-script' | 'robots-conflict' | 'script-src-with-content' | 'too-many-fetchpriority-high' | 'too-many-preconnects' | 'too-many-preloads' | 'twitter-handle-missing-at' | 'unresolved-template-param' | 'viewport-user-scalable';
120
- interface ValidationRuleOptions {
121
- 'charset-not-early': {
122
- maxPosition: number;
123
- };
124
- 'inline-script-size': {
125
- maxKB: number;
126
- };
127
- 'inline-style-size': {
128
- maxKB: number;
129
- };
130
- 'meta-beyond-1mb': {
131
- maxBytes: number;
132
- };
133
- 'too-many-fetchpriority-high': {
134
- max: number;
135
- };
136
- 'too-many-preloads': {
137
- max: number;
138
- };
139
- 'too-many-preconnects': {
140
- max: number;
141
- };
142
- }
143
- type RuleConfig<Id extends ValidationRuleId> = Id extends keyof ValidationRuleOptions ? RuleSeverity | [severity: RuleSeverity, options: ValidationRuleOptions[Id]] : RuleSeverity;
144
- type RulesConfig = {
145
- [K in ValidationRuleId]?: RuleConfig<K>;
146
- };
147
120
  interface HeadValidationRule {
148
121
  id: ValidationRuleId;
149
122
  message: string;
@@ -178,5 +151,5 @@ interface ValidatePluginOptions {
178
151
  }
179
152
  declare function ValidatePlugin(options?: ValidatePluginOptions): HeadPluginInput;
180
153
 
181
- export { AliasSortingPlugin, CanonicalPlugin, FlatMetaPlugin, InferSeoMetaPlugin, MinifyPlugin, PromisesPlugin, SafeInputPlugin, TemplateParamsPlugin, ValidatePlugin, defineHeadPlugin };
182
- export type { CanonicalPluginOptions, HeadValidationRule, MinifyPluginOptions, RuleConfig, RuleSeverity, RulesConfig, ValidatePluginOptions, ValidationRuleId, ValidationRuleOptions };
154
+ export { AliasSortingPlugin, CanonicalPlugin, FlatMetaPlugin, InferSeoMetaPlugin, MinifyPlugin, PromisesPlugin, RulesConfig, SafeInputPlugin, TemplateParamsPlugin, ValidatePlugin, ValidationRuleId, defineHeadPlugin };
155
+ export type { CanonicalPluginOptions, HeadValidationRule, MinifyPluginOptions, ValidatePluginOptions };
package/dist/plugins.d.ts CHANGED
@@ -1,5 +1,7 @@
1
- import { n as HeadPluginInput, U as Unhead, o as HeadPluginOptions } from './shared/unhead.BmdY3z1V.js';
2
- import { t as HeadTag } from './shared/unhead.BcynQ3qJ.js';
1
+ import { n as HeadPluginInput, U as Unhead, o as HeadPluginOptions } from './shared/unhead.gui9LmZS.js';
2
+ import { V as ValidationRuleId, R as RulesConfig } from './shared/unhead.Dl_lRDXb.js';
3
+ export { a as RuleConfig, b as RuleSeverity, c as ValidationRuleOptions } from './shared/unhead.Dl_lRDXb.js';
4
+ import { v as HeadTag } from './shared/unhead.DeoGMp34.js';
3
5
  import 'hookable';
4
6
 
5
7
  declare const AliasSortingPlugin: HeadPluginInput;
@@ -115,35 +117,6 @@ declare const SafeInputPlugin: HeadPluginInput;
115
117
 
116
118
  declare const TemplateParamsPlugin: HeadPluginInput;
117
119
 
118
- type RuleSeverity = 'warn' | 'info' | 'off';
119
- type ValidationRuleId = 'canonical-og-url-mismatch' | 'charset-not-early' | 'defer-on-module-script' | 'deprecated-option-mode' | 'deprecated-prop-body' | 'deprecated-prop-children' | 'deprecated-prop-hid-vmid' | 'duplicate-resource-hint' | 'empty-meta-content' | 'empty-title' | 'html-in-title' | 'inline-script-size' | 'inline-style-size' | 'meta-beyond-1mb' | 'missing-alias-sorting-plugin' | 'missing-description' | 'missing-template-params-plugin' | 'missing-title' | 'non-absolute-canonical' | 'non-absolute-og-url' | 'og-image-missing-dimensions' | 'og-missing-description' | 'og-missing-title' | 'possible-typo' | 'preconnect-missing-crossorigin' | 'prefetch-preload-conflict' | 'preload-async-defer-conflict' | 'preload-fetchpriority-conflict' | 'preload-font-crossorigin' | 'preload-missing-as' | 'preload-not-modulepreload' | 'redundant-dns-prefetch' | 'render-blocking-script' | 'robots-conflict' | 'script-src-with-content' | 'too-many-fetchpriority-high' | 'too-many-preconnects' | 'too-many-preloads' | 'twitter-handle-missing-at' | 'unresolved-template-param' | 'viewport-user-scalable';
120
- interface ValidationRuleOptions {
121
- 'charset-not-early': {
122
- maxPosition: number;
123
- };
124
- 'inline-script-size': {
125
- maxKB: number;
126
- };
127
- 'inline-style-size': {
128
- maxKB: number;
129
- };
130
- 'meta-beyond-1mb': {
131
- maxBytes: number;
132
- };
133
- 'too-many-fetchpriority-high': {
134
- max: number;
135
- };
136
- 'too-many-preloads': {
137
- max: number;
138
- };
139
- 'too-many-preconnects': {
140
- max: number;
141
- };
142
- }
143
- type RuleConfig<Id extends ValidationRuleId> = Id extends keyof ValidationRuleOptions ? RuleSeverity | [severity: RuleSeverity, options: ValidationRuleOptions[Id]] : RuleSeverity;
144
- type RulesConfig = {
145
- [K in ValidationRuleId]?: RuleConfig<K>;
146
- };
147
120
  interface HeadValidationRule {
148
121
  id: ValidationRuleId;
149
122
  message: string;
@@ -178,5 +151,5 @@ interface ValidatePluginOptions {
178
151
  }
179
152
  declare function ValidatePlugin(options?: ValidatePluginOptions): HeadPluginInput;
180
153
 
181
- export { AliasSortingPlugin, CanonicalPlugin, FlatMetaPlugin, InferSeoMetaPlugin, MinifyPlugin, PromisesPlugin, SafeInputPlugin, TemplateParamsPlugin, ValidatePlugin, defineHeadPlugin };
182
- export type { CanonicalPluginOptions, HeadValidationRule, MinifyPluginOptions, RuleConfig, RuleSeverity, RulesConfig, ValidatePluginOptions, ValidationRuleId, ValidationRuleOptions };
154
+ export { AliasSortingPlugin, CanonicalPlugin, FlatMetaPlugin, InferSeoMetaPlugin, MinifyPlugin, PromisesPlugin, RulesConfig, SafeInputPlugin, TemplateParamsPlugin, ValidatePlugin, ValidationRuleId, defineHeadPlugin };
155
+ export type { CanonicalPluginOptions, HeadValidationRule, MinifyPluginOptions, ValidatePluginOptions };
package/dist/plugins.mjs CHANGED
@@ -2,6 +2,7 @@ export { A as AliasSortingPlugin, P as PromisesPlugin, T as TemplateParamsPlugin
2
2
  import { d as defineHeadPlugin } from './shared/unhead.CUXLLRtV.mjs';
3
3
  export { F as FlatMetaPlugin, S as SafeInputPlugin } from './shared/unhead.A4ndrqqe.mjs';
4
4
  import { minifyJS, minifyCSS, minifyJSON } from './minify.mjs';
5
+ import { t as tagInputFromRuntime, o as tagPredicates, U as URL_META_KEYS, q as titleInputFromRuntime, h as headInputPredicates } from './shared/unhead.ebqUBTt1.mjs';
5
6
  import './shared/unhead.BGFxPGPQ.mjs';
6
7
  import './shared/unhead.JWUDzlIs.mjs';
7
8
  import './shared/unhead.fg-0ge_u.mjs';
@@ -201,155 +202,25 @@ function MinifyPlugin(options) {
201
202
  };
202
203
  }
203
204
 
204
- const URL_META_KEYS = /* @__PURE__ */ new Set([
205
- "og:url",
206
- "og:image",
207
- "og:image:url",
208
- "og:image:secure_url",
209
- "og:video",
210
- "og:video:url",
211
- "og:video:secure_url",
212
- "og:audio",
213
- "og:audio:url",
214
- "og:audio:secure_url",
215
- "twitter:image",
216
- "twitter:image:src",
217
- "twitter:player",
218
- "twitter:player:stream"
219
- ]);
220
- const KNOWN_META_PROPERTIES = /* @__PURE__ */ new Set([
221
- "article:author",
222
- "article:expiration_time",
223
- "article:modified_time",
224
- "article:published_time",
225
- "article:section",
226
- "article:tag",
227
- "book:author",
228
- "book:isbn",
229
- "book:release_date",
230
- "book:tag",
231
- "fb:app_id",
232
- "og:audio",
233
- "og:audio:secure_url",
234
- "og:audio:type",
235
- "og:audio:url",
236
- "og:description",
237
- "og:determiner",
238
- "og:image",
239
- "og:image:height",
240
- "og:image:secure_url",
241
- "og:image:type",
242
- "og:image:url",
243
- "og:image:width",
244
- "og:locale",
245
- "og:locale:alternate",
246
- "og:site_name",
247
- "og:title",
248
- "og:type",
249
- "og:url",
250
- "og:video",
251
- "og:video:height",
252
- "og:video:secure_url",
253
- "og:video:type",
254
- "og:video:url",
255
- "og:video:width",
256
- "profile:first_name",
257
- "profile:gender",
258
- "profile:last_name",
259
- "profile:username"
260
- ]);
261
- const KNOWN_META_NAMES = /* @__PURE__ */ new Set([
262
- "apple-itunes-app",
263
- "apple-mobile-web-app-capable",
264
- "apple-mobile-web-app-status-bar-style",
265
- "apple-mobile-web-app-title",
266
- "application-name",
267
- "author",
268
- "color-scheme",
269
- "creator",
270
- "description",
271
- "fb:app_id",
272
- "fediverse:creator",
273
- "format-detection",
274
- "generator",
275
- "google-site-verification",
276
- "google",
277
- "googlebot",
278
- "keywords",
279
- "mobile-web-app-capable",
280
- "msapplication-Config",
281
- "msapplication-TileColor",
282
- "msapplication-TileImage",
283
- "publisher",
284
- "rating",
285
- "referrer",
286
- "robots",
287
- "theme-color",
288
- "viewport",
289
- "twitter:app:id:googleplay",
290
- "twitter:app:id:ipad",
291
- "twitter:app:id:iphone",
292
- "twitter:app:name:googleplay",
293
- "twitter:app:name:ipad",
294
- "twitter:app:name:iphone",
295
- "twitter:app:url:googleplay",
296
- "twitter:app:url:ipad",
297
- "twitter:app:url:iphone",
298
- "twitter:card",
299
- "twitter:creator",
300
- "twitter:creator:id",
301
- "twitter:data:1",
302
- "twitter:data:2",
303
- "twitter:description",
304
- "twitter:image",
305
- "twitter:image:alt",
306
- "twitter:label:1",
307
- "twitter:label:2",
308
- "twitter:player",
309
- "twitter:player:height",
310
- "twitter:player:stream",
311
- "twitter:player:width",
312
- "twitter:site",
313
- "twitter:site:id",
314
- "twitter:title"
315
- ]);
316
205
  const TEMPLATE_PARAM_RE = /%\w+(?:\.\w+)?%/;
317
- const MAX_SCALE_RE = /maximum-scale\s*=\s*1(?:\.0?)?(?:\s|,|$)/i;
318
- const USER_SCALABLE_NO_RE = /user-scalable\s*=\s*no(?:\s|,|$)/i;
319
- const NUMERIC_RE = /^\d+$/;
320
- const OG_PREFIX_RE = /^(?:og|article|book|profile|fb):/;
321
- const HTML_CHARS_RE = /[<>]/;
322
206
  const AT_PREFIX_RE = /^at\s+/;
323
- function levenshtein(a, b) {
324
- const m = a.length;
325
- const n = b.length;
326
- const d = Array.from({ length: n + 1 }, (_, i) => i);
327
- for (let i = 1; i <= m; i++) {
328
- let prev = i - 1;
329
- d[0] = i;
330
- for (let j = 1; j <= n; j++) {
331
- const tmp = d[j];
332
- d[j] = a[i - 1] === b[j - 1] ? prev : 1 + Math.min(prev, d[j], d[j - 1]);
333
- prev = tmp;
334
- }
335
- }
336
- return d[n];
337
- }
338
- function findClosestMatch(value, knownSet) {
339
- const threshold = value.length <= 8 ? 2 : 3;
340
- let best;
341
- let bestDist = threshold + 1;
342
- for (const known of knownSet) {
343
- if (Math.abs(known.length - value.length) > threshold)
344
- continue;
345
- const dist = levenshtein(value, known);
346
- if (dist < bestDist) {
347
- bestDist = dist;
348
- best = known;
349
- }
350
- }
351
- return best;
352
- }
207
+ const PREDICATE_SEVERITY = {
208
+ "defer-on-module-script": "info",
209
+ "deprecated-prop-body": "warn",
210
+ "deprecated-prop-children": "warn",
211
+ "deprecated-prop-hid-vmid": "warn",
212
+ "empty-meta-content": "warn",
213
+ "html-in-title": "warn",
214
+ "non-absolute-canonical": "warn",
215
+ "numeric-tag-priority": "info",
216
+ "possible-typo": "warn",
217
+ "preload-font-crossorigin": "warn",
218
+ "preload-missing-as": "warn",
219
+ "robots-conflict": "warn",
220
+ "script-src-with-content": "warn",
221
+ "twitter-handle-missing-at": "warn",
222
+ "viewport-user-scalable": "info"
223
+ };
353
224
  function isAbsoluteUrl(url) {
354
225
  return url.startsWith("http://") || url.startsWith("https://");
355
226
  }
@@ -432,7 +303,7 @@ function ValidatePlugin(options = {}) {
432
303
  if (tag.tag === "title")
433
304
  hasTitle = true;
434
305
  if (tag.tag === "meta") {
435
- const key = tag.props.property || tag.props.name;
306
+ const key = tag.props.property || (tag.props.name ? String(tag.props.name).toLowerCase() : void 0);
436
307
  if (key) {
437
308
  metaByKey.set(key, tag);
438
309
  if (key.startsWith("og:"))
@@ -446,12 +317,19 @@ function ValidatePlugin(options = {}) {
446
317
  if (tag.tag === "link" && tag.props.rel === "canonical")
447
318
  canonicalHref = tag.props.href;
448
319
  }
320
+ function emitFromPredicates(diagnostics, tag) {
321
+ for (const diag of diagnostics) {
322
+ const sev = PREDICATE_SEVERITY[diag.ruleId] ?? "warn";
323
+ report(diag.ruleId, diag.message, sev, tag);
324
+ }
325
+ }
449
326
  for (const tag of tags) {
450
327
  const { props } = tag;
451
- const metaKey = props.property || props.name;
452
- if (tag.tag === "link" && props.rel === "canonical" && props.href) {
453
- if (!isAbsoluteUrl(props.href))
454
- report("non-absolute-canonical", `Canonical URL should be absolute, received "${props.href}".`, "warn", tag);
328
+ const metaKey = props.property || (props.name ? String(props.name).toLowerCase() : void 0);
329
+ const tagInput = tagInputFromRuntime(tag);
330
+ if (tagInput) {
331
+ for (const predicate of Object.values(tagPredicates))
332
+ emitFromPredicates(predicate(tagInput), tag);
455
333
  }
456
334
  if (tag.tag === "meta" && metaKey && URL_META_KEYS.has(metaKey)) {
457
335
  const content = String(props.content ?? "");
@@ -460,57 +338,23 @@ function ValidatePlugin(options = {}) {
460
338
  }
461
339
  if (tag.tag === "meta" && metaKey) {
462
340
  const content = String(props.content ?? "");
463
- if ("content" in props && content === "")
464
- report("empty-meta-content", `Meta tag "${metaKey}" has empty content.`, "warn", tag);
465
341
  if (content && TEMPLATE_PARAM_RE.test(content))
466
342
  report("unresolved-template-param", `Unresolved template param in ${metaKey}: "${content}".`, "warn", tag);
467
- if (metaKey === "robots" && content) {
468
- const directives = content.toLowerCase().split(",").map((d) => d.trim());
469
- if (directives.includes("index") && directives.includes("noindex"))
470
- report("robots-conflict", `Robots meta has conflicting "index" and "noindex" directives.`, "warn", tag);
471
- if (directives.includes("follow") && directives.includes("nofollow"))
472
- report("robots-conflict", `Robots meta has conflicting "follow" and "nofollow" directives.`, "warn", tag);
473
- }
474
- if (metaKey === "viewport" && content) {
475
- if (USER_SCALABLE_NO_RE.test(content))
476
- report("viewport-user-scalable", `viewport has "user-scalable=no" which prevents zooming and harms accessibility.`, "info", tag);
477
- if (MAX_SCALE_RE.test(content))
478
- report("viewport-user-scalable", `viewport "maximum-scale=1" limits zooming and may harm accessibility.`, "info", tag);
479
- }
480
- if ((metaKey === "twitter:site" || metaKey === "twitter:creator") && content && !content.startsWith("@") && !NUMERIC_RE.test(content))
481
- report("twitter-handle-missing-at", `${metaKey} should start with "@", received "${content}".`, "warn", tag);
482
- if (props.property && !KNOWN_META_PROPERTIES.has(props.property) && OG_PREFIX_RE.test(props.property)) {
483
- const suggestion = findClosestMatch(props.property, KNOWN_META_PROPERTIES);
484
- if (suggestion)
485
- report("possible-typo", `Unknown meta property "${props.property}". Did you mean "${suggestion}"?`, "warn", tag);
486
- }
487
- if (props.name && !KNOWN_META_NAMES.has(props.name) && (props.name.startsWith("twitter:") || props.name.startsWith("fediverse:") || !props.name.includes(":"))) {
488
- const suggestion = findClosestMatch(props.name, KNOWN_META_NAMES);
489
- if (suggestion)
490
- report("possible-typo", `Unknown meta name "${props.name}". Did you mean "${suggestion}"?`, "warn", tag);
491
- }
492
343
  }
493
344
  if (tag.tag === "title") {
345
+ const titleInput = titleInputFromRuntime(tag);
346
+ if (titleInput) {
347
+ for (const diag of headInputPredicates["no-html-in-title"](titleInput))
348
+ report(diag.ruleId, diag.message, "warn", tag);
349
+ }
494
350
  const text = tag.textContent || "";
495
- if (HTML_CHARS_RE.test(text))
496
- report("html-in-title", `Title contains HTML characters which will be escaped, not rendered: "${text}".`, "warn", tag);
497
351
  if (TEMPLATE_PARAM_RE.test(text))
498
352
  report("unresolved-template-param", `Unresolved template param in title: "${text}".`, "warn", tag);
499
353
  if (!text.trim())
500
354
  report("empty-title", `Title tag is empty. If using titleTemplate, ensure it produces output.`, "warn", tag);
501
355
  }
502
- if (tag.tag === "link" && props.rel === "preload") {
503
- if (props.as === "font" && !("crossorigin" in props))
504
- report("preload-font-crossorigin", `Font preload requires "crossorigin" attribute \u2014 without it the font will be fetched twice.`, "warn", tag);
505
- if (!props.as)
506
- report("preload-missing-as", `Preload link is missing the required "as" attribute.`, "warn", tag);
507
- }
508
- if (tag.tag === "script" && props.src && (tag.innerHTML || tag.textContent))
509
- report("script-src-with-content", `Script has both "src" and inline content \u2014 the browser will ignore the inline content.`, "warn", tag);
510
356
  if (tag.tag === "script" && props.src && !props.async && !props.defer && props.type !== "module" && (!tag.tagPosition || tag.tagPosition === "head"))
511
357
  report("render-blocking-script", `Script "${props.src}" is render-blocking. Add "async", "defer", or use type="module" to avoid blocking the critical rendering path.`, "warn", tag);
512
- if (tag.tag === "script" && props.type === "module" && props.defer)
513
- report("defer-on-module-script", `"defer" is redundant on module scripts. Modules are deferred by default.`, "info", tag);
514
358
  if (tag.tag === "link" && props.rel === "preload" && props.fetchpriority === "low" && props.as !== "script")
515
359
  report("preload-fetchpriority-conflict", `Preload with fetchpriority="low" is contradictory \u2014 preload signals critical, low priority contradicts that.`, "warn", tag);
516
360
  if (tag.tag === "style" && (tag.innerHTML || tag.textContent)) {
@@ -602,14 +446,6 @@ function ValidatePlugin(options = {}) {
602
446
  }
603
447
  }
604
448
  }
605
- for (const tag of tags) {
606
- if ("children" in tag.props)
607
- report("deprecated-prop-children", `"children" was removed in v3. Use "innerHTML" instead.`, "warn", tag);
608
- if ("hid" in tag.props || "vmid" in tag.props)
609
- report("deprecated-prop-hid-vmid", `"${"hid" in tag.props ? "hid" : "vmid"}" was removed in v3. Use "key" instead.`, "warn", tag);
610
- if (tag.props.body === true)
611
- report("deprecated-prop-body", `"body: true" was removed in v3. Use "tagPosition: 'bodyClose'" instead.`, "warn", tag);
612
- }
613
449
  const { max: maxHighPriority } = resolveOptions(ruleConfig, "too-many-fetchpriority-high", { max: 2 });
614
450
  const highPriorityCount = tags.filter((t) => t.props.fetchpriority === "high").length;
615
451
  if (highPriorityCount > maxHighPriority)
@@ -1,8 +1,8 @@
1
- import { R as RecordingEntry } from './shared/unhead.m4TuRTvV.mjs';
2
- export { a as AsVoidFunctions, j as EventHandlerOptions, u as ScriptInstance, z as UseFunctionType, B as UseScriptContext, F as UseScriptInput, G as UseScriptOptions, I as UseScriptResolvedInput, J as UseScriptReturn, K as UseScriptStatus, W as WarmupStrategy } from './shared/unhead.m4TuRTvV.mjs';
3
- export { u as useScript } from './shared/unhead.DvqMLXpO.mjs';
1
+ import { R as RecordingEntry } from './shared/unhead.BoZ-Ul8T.mjs';
2
+ export { a as AsVoidFunctions, j as EventHandlerOptions, u as ScriptInstance, z as UseFunctionType, B as UseScriptContext, F as UseScriptInput, G as UseScriptOptions, I as UseScriptResolvedInput, J as UseScriptReturn, K as UseScriptStatus, W as WarmupStrategy } from './shared/unhead.BoZ-Ul8T.mjs';
3
+ export { u as useScript } from './shared/unhead.ClE7lB2Z.mjs';
4
4
  import 'hookable';
5
- import './shared/unhead.BcynQ3qJ.mjs';
5
+ import './shared/unhead.DeoGMp34.mjs';
6
6
 
7
7
  declare function createSpyProxy<T extends Record<string, any> | any[]>(target: T, onApply: (stack: RecordingEntry[][]) => void): T;
8
8
 
package/dist/scripts.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { R as RecordingEntry } from './shared/unhead.BmdY3z1V.js';
2
- export { a as AsVoidFunctions, j as EventHandlerOptions, u as ScriptInstance, z as UseFunctionType, B as UseScriptContext, F as UseScriptInput, G as UseScriptOptions, I as UseScriptResolvedInput, J as UseScriptReturn, K as UseScriptStatus, W as WarmupStrategy } from './shared/unhead.BmdY3z1V.js';
3
- export { u as useScript } from './shared/unhead.DoIxTwSF.js';
1
+ import { R as RecordingEntry } from './shared/unhead.gui9LmZS.js';
2
+ export { a as AsVoidFunctions, j as EventHandlerOptions, u as ScriptInstance, z as UseFunctionType, B as UseScriptContext, F as UseScriptInput, G as UseScriptOptions, I as UseScriptResolvedInput, J as UseScriptReturn, K as UseScriptStatus, W as WarmupStrategy } from './shared/unhead.gui9LmZS.js';
3
+ export { u as useScript } from './shared/unhead.CqVawd25.js';
4
4
  import 'hookable';
5
- import './shared/unhead.BcynQ3qJ.js';
5
+ import './shared/unhead.DeoGMp34.js';
6
6
 
7
7
  declare function createSpyProxy<T extends Record<string, any> | any[]>(target: T, onApply: (stack: RecordingEntry[][]) => void): T;
8
8
 
package/dist/server.d.mts CHANGED
@@ -1,7 +1,7 @@
1
- export { S as ServerUnhead, c as createHead } from './shared/unhead.BfINO8Du.mjs';
2
- import { r as RenderSSRHeadOptions, p as HeadRenderer, s as SSRHeadPayload, U as Unhead } from './shared/unhead.m4TuRTvV.mjs';
3
- export { e as CreateServerHeadOptions } from './shared/unhead.m4TuRTvV.mjs';
4
- import { t as HeadTag } from './shared/unhead.BcynQ3qJ.mjs';
1
+ export { S as ServerUnhead, c as createHead } from './shared/unhead.B2jfOxG1.mjs';
2
+ import { r as RenderSSRHeadOptions, p as HeadRenderer, s as SSRHeadPayload, U as Unhead } from './shared/unhead.BoZ-Ul8T.mjs';
3
+ export { e as CreateServerHeadOptions } from './shared/unhead.BoZ-Ul8T.mjs';
4
+ import { v as HeadTag } from './shared/unhead.DeoGMp34.mjs';
5
5
  import 'hookable';
6
6
 
7
7
  declare function createServerRenderer(options?: RenderSSRHeadOptions): HeadRenderer<SSRHeadPayload>;
package/dist/server.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- export { S as ServerUnhead, c as createHead } from './shared/unhead.9aHQrEvB.js';
2
- import { r as RenderSSRHeadOptions, p as HeadRenderer, s as SSRHeadPayload, U as Unhead } from './shared/unhead.BmdY3z1V.js';
3
- export { e as CreateServerHeadOptions } from './shared/unhead.BmdY3z1V.js';
4
- import { t as HeadTag } from './shared/unhead.BcynQ3qJ.js';
1
+ export { S as ServerUnhead, c as createHead } from './shared/unhead.DdarjSpi.js';
2
+ import { r as RenderSSRHeadOptions, p as HeadRenderer, s as SSRHeadPayload, U as Unhead } from './shared/unhead.gui9LmZS.js';
3
+ export { e as CreateServerHeadOptions } from './shared/unhead.gui9LmZS.js';
4
+ import { v as HeadTag } from './shared/unhead.DeoGMp34.js';
5
5
  import 'hookable';
6
6
 
7
7
  declare function createServerRenderer(options?: RenderSSRHeadOptions): HeadRenderer<SSRHeadPayload>;
@@ -1,6 +1,6 @@
1
1
  import { HookableCore } from 'hookable';
2
- import { U as Unhead, C as ClientHeadHooks, c as CreateClientHeadOptions } from './unhead.BmdY3z1V.js';
3
- import { at as ResolvableHead } from './unhead.BcynQ3qJ.js';
2
+ import { U as Unhead, C as ClientHeadHooks, c as CreateClientHeadOptions } from './unhead.gui9LmZS.js';
3
+ import { aw as ResolvableHead } from './unhead.DeoGMp34.js';
4
4
 
5
5
  interface ClientUnhead<T = ResolvableHead> extends Unhead<T, boolean> {
6
6
  hooks: HookableCore<ClientHeadHooks>;
@@ -1,6 +1,6 @@
1
1
  import { HookableCore } from 'hookable';
2
- import { U as Unhead, s as SSRHeadPayload, v as ServerHeadHooks, e as CreateServerHeadOptions } from './unhead.m4TuRTvV.mjs';
3
- import { at as ResolvableHead } from './unhead.BcynQ3qJ.mjs';
2
+ import { U as Unhead, s as SSRHeadPayload, v as ServerHeadHooks, e as CreateServerHeadOptions } from './unhead.BoZ-Ul8T.mjs';
3
+ import { aw as ResolvableHead } from './unhead.DeoGMp34.mjs';
4
4
 
5
5
  interface ServerUnhead<T = ResolvableHead> extends Unhead<T, SSRHeadPayload> {
6
6
  hooks: HookableCore<ServerHeadHooks>;
@@ -1,4 +1,4 @@
1
- import { t as HeadTag } from './unhead.BcynQ3qJ.mjs';
1
+ import { v as HeadTag } from './unhead.DeoGMp34.mjs';
2
2
 
3
3
  interface RenderDomHeadOptions {
4
4
  /**
@@ -1,5 +1,5 @@
1
- import { p as HeadRenderer, d as CreateHeadOptions, U as Unhead } from './unhead.BmdY3z1V.js';
2
- import { at as ResolvableHead } from './unhead.BcynQ3qJ.js';
1
+ import { p as HeadRenderer, d as CreateHeadOptions, U as Unhead } from './unhead.gui9LmZS.js';
2
+ import { aw as ResolvableHead } from './unhead.DeoGMp34.js';
3
3
 
4
4
  declare function createUnhead<T = ResolvableHead, R = unknown>(renderer: HeadRenderer<R>, resolvedOptions?: CreateHeadOptions): Unhead<T, R>;
5
5
 
@@ -1,4 +1,4 @@
1
- import { aq as RawInput, at as ResolvableHead, aF as ResolvableValue, ay as ResolvableProperties, G as GenericLink, D as DataKeys, aH as SchemaAugmentations, a3 as MetaGeneric, r as GenericScript, a_ as UnheadHtmlAttributes, aZ as UnheadBodyAttributesWithoutEvents } from './unhead.BcynQ3qJ.mjs';
1
+ import { at as RawInput, aw as ResolvableHead, aI as ResolvableValue, aB as ResolvableProperties, G as GenericLink, D as DataKeys, aK as SchemaAugmentations, a6 as MetaGeneric, t as GenericScript, b2 as UnheadHtmlAttributes, b1 as UnheadBodyAttributesWithoutEvents } from './unhead.DeoGMp34.mjs';
2
2
 
3
3
  type Base = RawInput<'base'>;
4
4
  type HtmlAttributes = RawInput<'htmlAttrs'>;
@@ -1,5 +1,5 @@
1
1
  import { HookableCore } from 'hookable';
2
- import { r as GenericScript, aK as ScriptHttpEvents, D as DataKeys, _ as MaybeEventFnHandlers, x as HttpEventAttributes, aH as SchemaAugmentations, t as HeadTag, at as ResolvableHead, aT as TagPosition, aU as TagPriority, ao as ProcessesTemplateParams, aG as ResolvesDuplicates, aW as TemplateParams } from './unhead.BcynQ3qJ.mjs';
2
+ import { t as GenericScript, aN as ScriptHttpEvents, D as DataKeys, a1 as MaybeEventFnHandlers, z as HttpEventAttributes, aK as SchemaAugmentations, v as HeadTag, aw as ResolvableHead, aX as TagPosition, aY as TagPriority, ar as ProcessesTemplateParams, aJ as ResolvesDuplicates, a_ as TemplateParams } from './unhead.DeoGMp34.mjs';
3
3
 
4
4
  type UseScriptStatus = 'awaitingLoad' | 'loading' | 'loaded' | 'error' | 'removed';
5
5
  type UseScriptContext<T extends Record<symbol | string, any>> = ScriptInstance<T>;
@@ -1,4 +1,4 @@
1
- import { U as Unhead, F as UseScriptInput, G as UseScriptOptions, J as UseScriptReturn } from './unhead.m4TuRTvV.mjs';
1
+ import { U as Unhead, F as UseScriptInput, G as UseScriptOptions, J as UseScriptReturn } from './unhead.BoZ-Ul8T.mjs';
2
2
 
3
3
  /**
4
4
  * Load third-party scripts with SSR support and a proxied API.
@@ -1,4 +1,4 @@
1
- import { U as Unhead, F as UseScriptInput, G as UseScriptOptions, J as UseScriptReturn } from './unhead.BmdY3z1V.js';
1
+ import { U as Unhead, F as UseScriptInput, G as UseScriptOptions, J as UseScriptReturn } from './unhead.gui9LmZS.js';
2
2
 
3
3
  /**
4
4
  * Load third-party scripts with SSR support and a proxied API.