vuetify-nuxt-module 0.15.2 → 0.16.1
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/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -14,7 +14,7 @@ import { pathToFileURL } from 'node:url';
|
|
|
14
14
|
import { parseQuery, parseURL } from 'ufo';
|
|
15
15
|
import destr from 'destr';
|
|
16
16
|
|
|
17
|
-
const version = "0.
|
|
17
|
+
const version = "0.16.1";
|
|
18
18
|
|
|
19
19
|
const VIRTUAL_VUETIFY_CONFIGURATION = "virtual:vuetify-configuration";
|
|
20
20
|
const RESOLVED_VIRTUAL_VUETIFY_CONFIGURATION = `/@nuxt-vuetify-configuration/${VIRTUAL_VUETIFY_CONFIGURATION.slice("virtual:".length)}`;
|
|
@@ -7,12 +7,14 @@ export interface ClientHintRequestFeatures {
|
|
|
7
7
|
prefersReducedMotionAvailable: boolean
|
|
8
8
|
viewportHeightAvailable: boolean
|
|
9
9
|
viewportWidthAvailable: boolean
|
|
10
|
+
devicePixelRatioAvailable: boolean
|
|
10
11
|
}
|
|
11
12
|
export interface SSRClientHints extends ClientHintRequestFeatures {
|
|
12
13
|
prefersColorScheme?: 'dark' | 'light' | 'no-preference'
|
|
13
14
|
prefersReducedMotion?: 'no-preference' | 'reduce'
|
|
14
15
|
viewportHeight?: number
|
|
15
16
|
viewportWidth?: number
|
|
17
|
+
devicePixelRatio?: number
|
|
16
18
|
colorSchemeFromCookie?: string
|
|
17
19
|
colorSchemeCookie?: string
|
|
18
20
|
}
|
|
@@ -44,46 +44,46 @@ const plugin = defineNuxtPlugin({
|
|
|
44
44
|
if (viewportSize && viewportWidthAvailable)
|
|
45
45
|
window.location.reload();
|
|
46
46
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if (vuetifyOptions.theme === false) {
|
|
59
|
-
vuetifyOptions.theme = { defaultTheme: state.value.colorSchemeFromCookie ?? prefersColorSchemeOptions.defaultTheme };
|
|
60
|
-
} else {
|
|
61
|
-
vuetifyOptions.theme = vuetifyOptions.theme ?? {};
|
|
62
|
-
vuetifyOptions.theme.defaultTheme = state.value.colorSchemeFromCookie ?? prefersColorSchemeOptions.defaultTheme;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
});
|
|
47
|
+
nuxtApp.hook("vuetify:before-create", ({ vuetifyOptions }) => {
|
|
48
|
+
if (viewportSize) {
|
|
49
|
+
const clientWidth = state.value.viewportWidth;
|
|
50
|
+
const clientHeight = state.value.viewportHeight;
|
|
51
|
+
vuetifyOptions.ssr = typeof clientWidth === "number" ? {
|
|
52
|
+
clientWidth,
|
|
53
|
+
clientHeight
|
|
54
|
+
} : true;
|
|
55
|
+
} else {
|
|
56
|
+
vuetifyOptions.ssr = true;
|
|
57
|
+
}
|
|
66
58
|
if (prefersColorScheme && prefersColorSchemeOptions) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const parseCookieName = `${cookieName}=`;
|
|
73
|
-
const cookieEntry = `${parseCookieName}${state.value.colorSchemeFromCookie ?? prefersColorSchemeOptions.defaultTheme};`;
|
|
74
|
-
watch(vuetify.theme.global.name, (newThemeName) => {
|
|
75
|
-
document.cookie = themeCookie.replace(cookieEntry, `${cookieName}=${newThemeName};`);
|
|
76
|
-
});
|
|
77
|
-
if (prefersColorSchemeOptions.useBrowserThemeOnly) {
|
|
78
|
-
const { darkThemeName, lightThemeName } = prefersColorSchemeOptions;
|
|
79
|
-
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)");
|
|
80
|
-
prefersDark.addEventListener("change", (e) => {
|
|
81
|
-
vuetify.theme.global.name.value = e.matches ? darkThemeName : lightThemeName;
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
});
|
|
59
|
+
if (vuetifyOptions.theme === false) {
|
|
60
|
+
vuetifyOptions.theme = { defaultTheme: state.value.colorSchemeFromCookie ?? prefersColorSchemeOptions.defaultTheme };
|
|
61
|
+
} else {
|
|
62
|
+
vuetifyOptions.theme = vuetifyOptions.theme ?? {};
|
|
63
|
+
vuetifyOptions.theme.defaultTheme = state.value.colorSchemeFromCookie ?? prefersColorSchemeOptions.defaultTheme;
|
|
85
64
|
}
|
|
86
65
|
}
|
|
66
|
+
});
|
|
67
|
+
if (prefersColorScheme && prefersColorSchemeOptions) {
|
|
68
|
+
const themeCookie = state.value.colorSchemeCookie;
|
|
69
|
+
if (themeCookie) {
|
|
70
|
+
nuxtApp.hook("app:beforeMount", () => {
|
|
71
|
+
const vuetify = useNuxtApp().$vuetify;
|
|
72
|
+
const cookieName = prefersColorSchemeOptions.cookieName;
|
|
73
|
+
const parseCookieName = `${cookieName}=`;
|
|
74
|
+
const cookieEntry = `${parseCookieName}${state.value.colorSchemeFromCookie ?? prefersColorSchemeOptions.defaultTheme};`;
|
|
75
|
+
watch(vuetify.theme.global.name, (newThemeName) => {
|
|
76
|
+
document.cookie = themeCookie.replace(cookieEntry, `${cookieName}=${newThemeName};`);
|
|
77
|
+
});
|
|
78
|
+
if (prefersColorSchemeOptions.useBrowserThemeOnly) {
|
|
79
|
+
const { darkThemeName, lightThemeName } = prefersColorSchemeOptions;
|
|
80
|
+
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)");
|
|
81
|
+
prefersDark.addEventListener("change", (e) => {
|
|
82
|
+
vuetify.theme.global.name.value = e.matches ? darkThemeName : lightThemeName;
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
87
|
}
|
|
88
88
|
return {
|
|
89
89
|
provide: reactive({
|
|
@@ -17,16 +17,18 @@ const AcceptClientHintsHeaders = {
|
|
|
17
17
|
prefersColorScheme: "Sec-CH-Prefers-Color-Scheme",
|
|
18
18
|
prefersReducedMotion: "Sec-CH-Prefers-Reduced-Motion",
|
|
19
19
|
viewportHeight: "Sec-CH-Viewport-Height",
|
|
20
|
-
viewportWidth: "Sec-CH-Viewport-Width"
|
|
20
|
+
viewportWidth: "Sec-CH-Viewport-Width",
|
|
21
|
+
devicePixelRatio: "Sec-CH-DPR"
|
|
21
22
|
};
|
|
22
23
|
const AcceptClientHintsRequestHeaders = Object.entries(AcceptClientHintsHeaders).reduce((acc, [key, value]) => {
|
|
23
24
|
acc[key] = value.toLowerCase();
|
|
24
25
|
return acc;
|
|
25
26
|
}, {});
|
|
26
|
-
const
|
|
27
|
+
const SecChUaMobile = "Sec-CH-UA-Mobile".toLowerCase();
|
|
28
|
+
const HttpRequestHeaders = Array.from(Object.values(AcceptClientHintsRequestHeaders)).concat("user-agent", "cookie", SecChUaMobile);
|
|
27
29
|
const plugin = defineNuxtPlugin({
|
|
28
30
|
name: "vuetify:client-hints:server:plugin",
|
|
29
|
-
order:
|
|
31
|
+
order: 24,
|
|
30
32
|
parallel: true,
|
|
31
33
|
setup(nuxtApp) {
|
|
32
34
|
const state = useState(VuetifyHTTPClientHints);
|
|
@@ -75,19 +77,24 @@ const chromiumBasedBrowserFeatures = {
|
|
|
75
77
|
prefersColorScheme: (_, v) => v[0] >= 93,
|
|
76
78
|
prefersReducedMotion: (_, v) => v[0] >= 108,
|
|
77
79
|
viewportHeight: (_, v) => v[0] >= 108,
|
|
78
|
-
viewportWidth: (_, v) => v[0] >= 108
|
|
80
|
+
viewportWidth: (_, v) => v[0] >= 108,
|
|
81
|
+
devicePixelRatio: (_, v) => v[0] >= 46
|
|
79
82
|
};
|
|
80
83
|
const allowedBrowsers = [
|
|
81
84
|
// 'edge',
|
|
82
85
|
// 'edge-ios',
|
|
83
86
|
["chrome", chromiumBasedBrowserFeatures],
|
|
84
|
-
["edge-chromium",
|
|
87
|
+
["edge-chromium", {
|
|
88
|
+
...chromiumBasedBrowserFeatures,
|
|
89
|
+
devicePixelRatio: (_, v) => v[0] >= 79
|
|
90
|
+
}],
|
|
85
91
|
["chromium-webview", chromiumBasedBrowserFeatures],
|
|
86
92
|
["opera", {
|
|
87
93
|
prefersColorScheme: (android, v) => v[0] >= (android ? 66 : 79),
|
|
88
94
|
prefersReducedMotion: (android, v) => v[0] >= (android ? 73 : 94),
|
|
89
95
|
viewportHeight: (android, v) => v[0] >= (android ? 73 : 94),
|
|
90
|
-
viewportWidth: (android, v) => v[0] >= (android ? 73 : 94)
|
|
96
|
+
viewportWidth: (android, v) => v[0] >= (android ? 73 : 94),
|
|
97
|
+
devicePixelRatio: (_, v) => v[0] >= 33
|
|
91
98
|
}]
|
|
92
99
|
];
|
|
93
100
|
const ClientHeaders = ["Accept-CH", "Vary", "Critical-CH"];
|
|
@@ -111,13 +118,14 @@ function browserFeatureAvailable(userAgent, feature) {
|
|
|
111
118
|
return false;
|
|
112
119
|
}
|
|
113
120
|
}
|
|
114
|
-
function lookupClientHints(userAgent, ssrClientHintsConfiguration2) {
|
|
121
|
+
function lookupClientHints(userAgent, ssrClientHintsConfiguration2, headers) {
|
|
115
122
|
const features = {
|
|
116
123
|
firstRequest: true,
|
|
117
124
|
prefersColorSchemeAvailable: false,
|
|
118
125
|
prefersReducedMotionAvailable: false,
|
|
119
126
|
viewportHeightAvailable: false,
|
|
120
|
-
viewportWidthAvailable: false
|
|
127
|
+
viewportWidthAvailable: false,
|
|
128
|
+
devicePixelRatioAvailable: false
|
|
121
129
|
};
|
|
122
130
|
if (userAgent == null || userAgent.type !== "browser")
|
|
123
131
|
return features;
|
|
@@ -128,11 +136,14 @@ function lookupClientHints(userAgent, ssrClientHintsConfiguration2) {
|
|
|
128
136
|
if (ssrClientHintsConfiguration2.viewportSize) {
|
|
129
137
|
features.viewportHeightAvailable = browserFeatureAvailable(userAgent, "viewportHeight");
|
|
130
138
|
features.viewportWidthAvailable = browserFeatureAvailable(userAgent, "viewportWidth");
|
|
139
|
+
const mobileHeader = headers[SecChUaMobile];
|
|
140
|
+
if (mobileHeader === "?1")
|
|
141
|
+
features.devicePixelRatioAvailable = browserFeatureAvailable(userAgent, "devicePixelRatio");
|
|
131
142
|
}
|
|
132
143
|
return features;
|
|
133
144
|
}
|
|
134
145
|
function collectClientHints(userAgent, ssrClientHintsConfiguration2, headers) {
|
|
135
|
-
const hints = lookupClientHints(userAgent, ssrClientHintsConfiguration2);
|
|
146
|
+
const hints = lookupClientHints(userAgent, ssrClientHintsConfiguration2, headers);
|
|
136
147
|
if (ssrClientHintsConfiguration2.prefersColorScheme) {
|
|
137
148
|
if (ssrClientHintsConfiguration2.prefersColorSchemeOptions) {
|
|
138
149
|
const cookieName = ssrClientHintsConfiguration2.prefersColorSchemeOptions.cookieName;
|
|
@@ -193,6 +204,22 @@ function collectClientHints(userAgent, ssrClientHintsConfiguration2, headers) {
|
|
|
193
204
|
} else {
|
|
194
205
|
hints.viewportWidth = ssrClientHintsConfiguration2.clientWidth;
|
|
195
206
|
}
|
|
207
|
+
if (hints.devicePixelRatioAvailable && ssrClientHintsConfiguration2.viewportSize) {
|
|
208
|
+
const header = headers[AcceptClientHintsRequestHeaders.devicePixelRatio];
|
|
209
|
+
if (header) {
|
|
210
|
+
hints.firstRequest = false;
|
|
211
|
+
try {
|
|
212
|
+
hints.devicePixelRatio = Number.parseFloat(header);
|
|
213
|
+
if (!Number.isNaN(hints.devicePixelRatio) && hints.devicePixelRatio > 0) {
|
|
214
|
+
if (typeof hints.viewportWidth === "number")
|
|
215
|
+
hints.viewportWidth = Math.round(hints.viewportWidth / hints.devicePixelRatio);
|
|
216
|
+
if (typeof hints.viewportHeight === "number")
|
|
217
|
+
hints.viewportHeight = Math.round(hints.viewportHeight / hints.devicePixelRatio);
|
|
218
|
+
}
|
|
219
|
+
} catch {
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
196
223
|
return hints;
|
|
197
224
|
}
|
|
198
225
|
function writeClientHintHeaders(key, headers) {
|
|
@@ -209,6 +236,8 @@ function writeClientHintsResponseHeaders(clientHintsRequest, ssrClientHintsConfi
|
|
|
209
236
|
if (ssrClientHintsConfiguration2.viewportSize && clientHintsRequest.viewportHeightAvailable && clientHintsRequest.viewportWidthAvailable) {
|
|
210
237
|
writeClientHintHeaders(AcceptClientHintsHeaders.viewportHeight, headers);
|
|
211
238
|
writeClientHintHeaders(AcceptClientHintsHeaders.viewportWidth, headers);
|
|
239
|
+
if (clientHintsRequest.devicePixelRatioAvailable)
|
|
240
|
+
writeClientHintHeaders(AcceptClientHintsHeaders.devicePixelRatio, headers);
|
|
212
241
|
}
|
|
213
242
|
if (Object.keys(headers).length === 0)
|
|
214
243
|
return;
|