@vueuse/head
Advanced tools
Comparing version 0.7.11 to 0.7.12
@@ -24,23 +24,42 @@ import * as vue from 'vue'; | ||
} | ||
interface HasRenderPriority { | ||
/** | ||
* The priority for rendering the tag, without this all tags are rendered as they are registered | ||
* (besides some special tags). | ||
* | ||
* The following special tags have default priorities: | ||
* * -2 <meta charset ...> | ||
* * -1 <base> | ||
* * 0 <meta http-equiv="content-security-policy" ...> | ||
* | ||
* All other tags have a default priority of 10: <meta>, <script>, <link>, <style>, etc | ||
* | ||
* @warn Experimental feature. Only available when rendering SSR | ||
*/ | ||
renderPriority?: number; | ||
} | ||
interface HeadAugmentations { | ||
base: HandlesDuplicates & { | ||
base: { | ||
key?: never; | ||
renderPriority?: never; | ||
body?: never; | ||
children?: never; | ||
}; | ||
link: RendersToBody & { | ||
link: HasRenderPriority & RendersToBody & { | ||
key?: never; | ||
children?: never; | ||
}; | ||
meta: HandlesDuplicates & { | ||
meta: HasRenderPriority & HandlesDuplicates & { | ||
children?: never; | ||
body?: never; | ||
}; | ||
style: RendersToBody & RendersInnerContent & { | ||
style: HasRenderPriority & RendersToBody & RendersInnerContent & { | ||
key?: never; | ||
}; | ||
script: RendersToBody & RendersInnerContent & HandlesDuplicates; | ||
noscript: RendersToBody & RendersInnerContent & { | ||
script: HasRenderPriority & RendersToBody & RendersInnerContent & HandlesDuplicates; | ||
noscript: HasRenderPriority & RendersToBody & RendersInnerContent & { | ||
key?: never; | ||
}; | ||
htmlAttrs: { | ||
renderPriority?: never; | ||
key?: never; | ||
@@ -51,2 +70,3 @@ children?: never; | ||
bodyAttrs: { | ||
renderPriority?: never; | ||
key?: never; | ||
@@ -67,4 +87,3 @@ children?: never; | ||
tag: TagKeys; | ||
props: { | ||
body?: boolean; | ||
props: HandlesDuplicates & HasRenderPriority & RendersToBody & RendersInnerContent & { | ||
[k: string]: any; | ||
@@ -94,4 +113,4 @@ }; | ||
declare const renderHeadToString: (head: HeadClient) => HTMLResult; | ||
declare const Head: vue.DefineComponent<{}, () => null, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, vue.EmitsOptions, string, vue.VNodeProps & vue.AllowedComponentProps & vue.ComponentCustomProps, Readonly<vue.ExtractPropTypes<{}>>, {}>; | ||
declare const Head: vue.DefineComponent<{}, () => null, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.VNodeProps & vue.AllowedComponentProps & vue.ComponentCustomProps, Readonly<vue.ExtractPropTypes<{}>>, {}>; | ||
export { HTMLResult, Head, HeadAttrs, HeadClient, HeadTag, createHead, injectHead, renderHeadToString, useHead }; | ||
export { HTMLResult, HandlesDuplicates, HasRenderPriority, Head, HeadAttrs, HeadClient, HeadObject, HeadObjectPlain, HeadTag, RendersInnerContent, RendersToBody, TagKeys, createHead, injectHead, renderHeadToString, useHead }; |
@@ -0,22 +1,6 @@ | ||
"use strict"; | ||
var __defProp = Object.defineProperty; | ||
var __defProps = Object.defineProperties; | ||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
var __getOwnPropDescs = Object.getOwnPropertyDescriptors; | ||
var __getOwnPropNames = Object.getOwnPropertyNames; | ||
var __getOwnPropSymbols = Object.getOwnPropertySymbols; | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
var __propIsEnum = Object.prototype.propertyIsEnumerable; | ||
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; | ||
var __spreadValues = (a, b) => { | ||
for (var prop in b || (b = {})) | ||
if (__hasOwnProp.call(b, prop)) | ||
__defNormalProp(a, prop, b[prop]); | ||
if (__getOwnPropSymbols) | ||
for (var prop of __getOwnPropSymbols(b)) { | ||
if (__propIsEnum.call(b, prop)) | ||
__defNormalProp(a, prop, b[prop]); | ||
} | ||
return a; | ||
}; | ||
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); | ||
var __export = (target, all) => { | ||
@@ -63,3 +47,3 @@ for (var name in all) | ||
let value = attrs[key]; | ||
if (key === "key" || value === false) { | ||
if (key === "renderPriority" || key === "key" || value === false) { | ||
continue; | ||
@@ -112,10 +96,29 @@ } | ||
// src/index.ts | ||
var getTagKey = (props) => { | ||
const names = ["key", "id", "name", "property"]; | ||
for (const n of names) { | ||
const value = typeof props.getAttribute === "function" ? props.hasAttribute(n) ? props.getAttribute(n) : void 0 : props[n]; | ||
var getTagDeduper = (tag) => { | ||
if (!["meta", "base", "script", "link"].includes(tag.tag)) { | ||
return false; | ||
} | ||
const { props, tag: tagName } = tag; | ||
if (tagName === "base") { | ||
return true; | ||
} | ||
if (tagName === "link" && props.rel === "canonical") { | ||
return { propValue: "canonical" }; | ||
} | ||
if (props.charset) { | ||
return { propKey: "charset" }; | ||
} | ||
const name = ["key", "id", "name", "property", "http-equiv"]; | ||
for (const n of name) { | ||
let value = void 0; | ||
if (typeof props.getAttribute === "function" && props.hasAttribute(n)) { | ||
value = props.getAttribute(n); | ||
} else { | ||
value = props[n]; | ||
} | ||
if (value !== void 0) { | ||
return { name: n, value }; | ||
return { propValue: n }; | ||
} | ||
} | ||
return false; | ||
}; | ||
@@ -161,3 +164,3 @@ var injectHead = () => { | ||
case "base": | ||
tags.push({ tag: key, props: __spreadValues({ key: "default" }, obj[key]) }); | ||
tags.push({ tag: key, props: { key: "default", ...obj[key] } }); | ||
break; | ||
@@ -271,3 +274,6 @@ default: | ||
}); | ||
headCountEl.setAttribute("content", "" + (headCount - oldHeadElements.length + newElements.filter((t) => !t.body).length)); | ||
headCountEl.setAttribute( | ||
"content", | ||
"" + (headCount - oldHeadElements.length + newElements.filter((t) => !t.body).length) | ||
); | ||
}; | ||
@@ -291,22 +297,30 @@ var createHead = (initHeadObject) => { | ||
tags.forEach((tag) => { | ||
if (tag.tag === "meta" || tag.tag === "base" || tag.tag === "script") { | ||
const key = getTagKey(tag.props); | ||
if (key) { | ||
let index = -1; | ||
for (let i = 0; i < deduped.length; i++) { | ||
const prev = deduped[i]; | ||
const prevValue = prev.props[key.name]; | ||
const nextValue = tag.props[key.name]; | ||
if (prev.tag === tag.tag && prevValue === nextValue) { | ||
index = i; | ||
break; | ||
} | ||
const dedupe = getTagDeduper(tag); | ||
if (dedupe) { | ||
let index = -1; | ||
for (let i = 0; i < deduped.length; i++) { | ||
const prev = deduped[i]; | ||
if (prev.tag !== tag.tag) { | ||
continue; | ||
} | ||
if (dedupe === true) { | ||
index = i; | ||
} else if (dedupe.propValue && (0, import_vue.unref)(prev.props[dedupe.propValue]) === (0, import_vue.unref)(tag.props[dedupe.propValue])) { | ||
index = i; | ||
} else if (dedupe.propKey && prev.props[dedupe.propKey] && tag.props[dedupe.propKey]) { | ||
index = i; | ||
} | ||
if (index !== -1) { | ||
deduped.splice(index, 1); | ||
break; | ||
} | ||
} | ||
if (index !== -1) { | ||
deduped.splice(index, 1); | ||
} | ||
} | ||
if (titleTemplate && tag.tag === "title") { | ||
tag.props.children = renderTemplate(titleTemplate, tag.props.children); | ||
tag.props.children = renderTemplate( | ||
titleTemplate, | ||
tag.props.children | ||
); | ||
} | ||
@@ -329,3 +343,3 @@ deduped.push(tag); | ||
const actualTags = {}; | ||
for (const tag of head.headTags) { | ||
for (const tag of head.headTags.sort(sortTags)) { | ||
if (tag.tag === "title") { | ||
@@ -382,2 +396,5 @@ title = tag.props.children; | ||
} | ||
if (tag.props.renderPriority) { | ||
delete tag.props.renderPriority; | ||
} | ||
let attrs = stringifyAttrs(tag.props); | ||
@@ -389,2 +406,24 @@ if (SELF_CLOSING_TAGS.includes(tag.tag)) { | ||
}; | ||
var sortTags = (aTag, bTag) => { | ||
const tagWeight = (tag) => { | ||
if (tag.props.renderPriority) { | ||
return tag.props.renderPriority; | ||
} | ||
switch (tag.tag) { | ||
case "base": | ||
return -1; | ||
case "meta": | ||
if (tag.props.charset) { | ||
return -2; | ||
} | ||
if (tag.props["http-equiv"] === "content-security-policy") { | ||
return 0; | ||
} | ||
return 10; | ||
default: | ||
return 10; | ||
} | ||
}; | ||
return tagWeight(aTag) - tagWeight(bTag); | ||
}; | ||
var renderHeadToString = (head) => { | ||
@@ -396,3 +435,3 @@ const tags = []; | ||
let bodyTags = []; | ||
for (const tag of head.headTags) { | ||
for (const tag of head.headTags.sort(sortTags)) { | ||
if (tag.tag === "title") { | ||
@@ -416,10 +455,12 @@ titleTag = tagToString(tag); | ||
get htmlAttrs() { | ||
return stringifyAttrs(__spreadProps(__spreadValues({}, htmlAttrs), { | ||
return stringifyAttrs({ | ||
...htmlAttrs, | ||
[HEAD_ATTRS_KEY]: Object.keys(htmlAttrs).join(",") | ||
})); | ||
}); | ||
}, | ||
get bodyAttrs() { | ||
return stringifyAttrs(__spreadProps(__spreadValues({}, bodyAttrs), { | ||
return stringifyAttrs({ | ||
...bodyAttrs, | ||
[HEAD_ATTRS_KEY]: Object.keys(bodyAttrs).join(",") | ||
})); | ||
}); | ||
}, | ||
@@ -435,5 +476,6 @@ get bodyTags() { | ||
return; | ||
const props = __spreadProps(__spreadValues({}, node.props), { | ||
const props = { | ||
...node.props, | ||
children: Array.isArray(node.children) ? node.children[0].children : node.children | ||
}); | ||
}; | ||
if (Array.isArray(obj[type])) { | ||
@@ -440,0 +482,0 @@ ; |
{ | ||
"name": "@vueuse/head", | ||
"packageManager": "pnpm@7.5.0", | ||
"version": "0.7.11", | ||
"version": "0.7.12", | ||
"license": "MIT", | ||
@@ -60,7 +60,7 @@ "description": "Document head manager for Vue 3. SSR ready.", | ||
"@happy-dom/global-registrator": "^6.0.4", | ||
"@vitejs/plugin-vue": "^3.0.1", | ||
"@vitejs/plugin-vue-jsx": "^2.0.0", | ||
"@vue/compiler-sfc": "^3.2.37", | ||
"@vue/server-renderer": "^3.2.37", | ||
"ava": "^4.3.1", | ||
"@vitejs/plugin-vue": "^3.1.0", | ||
"@vitejs/plugin-vue-jsx": "^2.0.1", | ||
"@vue/compiler-sfc": "^3.2.39", | ||
"@vue/server-renderer": "^3.2.39", | ||
"ava": "^4.3.3", | ||
"chrome-location": "^1.2.1", | ||
@@ -70,13 +70,13 @@ "esbuild-register": "^3.3.3", | ||
"happy-dom": "^6.0.4", | ||
"kanpai": "^0.10.1", | ||
"kanpai": "^0.11.0", | ||
"lint-staged": "^13.0.3", | ||
"node-fetch": "^3.2.9", | ||
"playwright-core": "^1.24.0", | ||
"node-fetch": "^3.2.10", | ||
"playwright-core": "^1.25.2", | ||
"prettier": "^2.7.1", | ||
"simple-git-hooks": "^2.8.0", | ||
"tsup": "^6.1.3", | ||
"typescript": "^4.7.4", | ||
"vite": "^3.0.2", | ||
"vue": "^3.2.37", | ||
"vue-router": "^4.1.2" | ||
"tsup": "^6.2.3", | ||
"typescript": "^4.8.3", | ||
"vite": "^3.1.2", | ||
"vue": "^3.2.39", | ||
"vue-router": "^4.1.5" | ||
}, | ||
@@ -87,4 +87,4 @@ "peerDependencies": { | ||
"dependencies": { | ||
"@zhead/schema-vue": "^0.7.1" | ||
"@zhead/schema-vue": "^0.7.3" | ||
} | ||
} |
@@ -179,2 +179,37 @@ # @vueuse/head | ||
#### Render Priority | ||
> :warning: Experimental feature | ||
> Only available when rendering SSR. | ||
To set the render priority of a tag you can use the `renderPriority` attribute: | ||
```ts | ||
useHead({ | ||
script: [ | ||
{ | ||
src: "/not-important-script.js", | ||
}, | ||
], | ||
}) | ||
useHead({ | ||
script: [ | ||
// will render first | ||
{ | ||
src: "/very-important-script.js", | ||
renderPriority: 1 // default is 10, so will be first | ||
}, | ||
], | ||
}) | ||
``` | ||
The following special tags have default priorities: | ||
- -2 <meta charset ...> | ||
- -1 <base> | ||
- 0 <meta http-equiv="content-security-policy" ...> | ||
All other tags have a default priority of 10: <meta>, <script>, <link>, <style>, etc | ||
### `<Head>` | ||
@@ -181,0 +216,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
41869
1153
260
+ Addedmagic-string@0.30.14(transitive)
+ Addednanoid@3.3.8(transitive)
- Removedmagic-string@0.30.13(transitive)
- Removednanoid@3.3.7(transitive)
Updated@zhead/schema-vue@^0.7.3