@inzombieland/nuxt-common 0.0.3 → 0.0.5
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/LICENSE +8 -0
- package/assets/css/layer.css +305 -0
- package/module.cjs +5 -0
- package/module.d.mts +7 -0
- package/module.d.ts +7 -0
- package/module.json +9 -0
- package/module.mjs +70 -0
- package/package.json +5 -3
- package/runtime/AppProvider.vue +129 -0
- package/runtime/SidebarProvider.vue +138 -0
- package/runtime/api/account/account.get.d.ts +2 -0
- package/runtime/api/account/account.get.mjs +19 -0
- package/runtime/api/account/authcheck.get.d.ts +8 -0
- package/runtime/api/account/authcheck.get.mjs +28 -0
- package/runtime/api/account/default-handler.d.ts +2 -0
- package/runtime/api/account/default-handler.mjs +37 -0
- package/runtime/api/account/middleware.d.ts +2 -0
- package/runtime/api/account/middleware.mjs +18 -0
- package/runtime/api/account/token.get.d.ts +2 -0
- package/runtime/api/account/token.get.mjs +31 -0
- package/runtime/api/index.d.ts +37 -0
- package/runtime/api/index.mjs +26 -0
- package/runtime/api/user-actions.d.ts +118 -0
- package/runtime/api/user-actions.mjs +165 -0
- package/runtime/composables/use-active-sessions.d.ts +5 -0
- package/runtime/composables/use-active-sessions.mjs +15 -0
- package/runtime/composables/use-api-fetch.d.ts +3 -0
- package/runtime/composables/use-api-fetch.mjs +3 -0
- package/runtime/composables/use-helpers.d.ts +16 -0
- package/runtime/composables/use-helpers.mjs +10 -0
- package/runtime/composables/use-layer-manager.d.ts +3 -0
- package/runtime/composables/use-layer-manager.mjs +3 -0
- package/runtime/composables/use-subscribe.d.ts +10 -0
- package/runtime/composables/use-subscribe.mjs +22 -0
- package/runtime/composables/use-toggle-sidebar.d.ts +3 -0
- package/runtime/composables/use-toggle-sidebar.mjs +8 -0
- package/runtime/composables/use-user-actions.d.ts +2 -0
- package/runtime/composables/use-user-actions.mjs +4 -0
- package/runtime/composables/use-user.d.ts +3 -0
- package/runtime/composables/use-user.mjs +3 -0
- package/runtime/composables/use-validators.d.ts +8 -0
- package/runtime/composables/use-validators.mjs +17 -0
- package/runtime/middleware/auth.d.ts +2 -0
- package/runtime/middleware/auth.mjs +10 -0
- package/runtime/middleware/guest.d.ts +2 -0
- package/runtime/middleware/guest.mjs +12 -0
- package/runtime/middleware/index.d.ts +4 -0
- package/runtime/middleware/index.mjs +4 -0
- package/runtime/middleware/locale.global.d.ts +2 -0
- package/runtime/middleware/locale.global.mjs +13 -0
- package/runtime/packages/api/api-client.d.ts +8 -0
- package/runtime/packages/api/api-client.mjs +150 -0
- package/runtime/packages/api/bus.d.ts +7 -0
- package/runtime/packages/api/bus.mjs +22 -0
- package/runtime/packages/api/comet-client.d.ts +11 -0
- package/runtime/packages/api/comet-client.mjs +73 -0
- package/runtime/packages/api/get-user.d.ts +8 -0
- package/runtime/packages/api/get-user.mjs +54 -0
- package/runtime/packages/api/get-visitor.d.ts +11 -0
- package/runtime/packages/api/get-visitor.mjs +32 -0
- package/runtime/packages/api/helpers/api-helper.d.ts +6 -0
- package/runtime/packages/api/helpers/api-helper.mjs +99 -0
- package/runtime/packages/api/helpers/current-device.d.ts +67 -0
- package/runtime/packages/api/helpers/current-device.mjs +368 -0
- package/runtime/packages/api/helpers/date-helper.d.ts +15 -0
- package/runtime/packages/api/helpers/date-helper.mjs +231 -0
- package/runtime/packages/api/helpers/index.d.ts +4 -0
- package/runtime/packages/api/helpers/index.mjs +15 -0
- package/runtime/packages/api/index.d.ts +26 -0
- package/runtime/packages/api/index.mjs +50 -0
- package/runtime/packages/api/package.json +20 -0
- package/runtime/packages/api/refresh-token.d.ts +2 -0
- package/runtime/packages/api/refresh-token.mjs +39 -0
- package/runtime/packages/api/types.d.ts +51 -0
- package/runtime/packages/api/types.mjs +0 -0
- package/runtime/packages/api/use-api-actions.d.ts +13 -0
- package/runtime/packages/api/use-api-actions.mjs +5 -0
- package/runtime/packages/api/use-user.d.ts +47 -0
- package/runtime/packages/api/use-user.mjs +5 -0
- package/runtime/packages/helpers/index.d.ts +3 -0
- package/runtime/packages/helpers/index.mjs +14 -0
- package/runtime/packages/helpers/package.json +11 -0
- package/runtime/packages/helpers/phone-helper.d.ts +13 -0
- package/runtime/packages/helpers/phone-helper.mjs +58 -0
- package/runtime/packages/helpers/string-helper.d.ts +4 -0
- package/runtime/packages/helpers/string-helper.mjs +8 -0
- package/runtime/packages/layer-manager/LayerComponent.vue +54 -0
- package/runtime/packages/layer-manager/LayersProvider.vue +171 -0
- package/runtime/packages/layer-manager/index.d.ts +2 -0
- package/runtime/packages/layer-manager/index.mjs +2 -0
- package/runtime/packages/layer-manager/package.json +11 -0
- package/runtime/packages/layer-manager/types.d.ts +8 -0
- package/runtime/packages/layer-manager/types.mjs +0 -0
- package/runtime/packages/layer-manager/use-layer-actions.d.ts +23 -0
- package/runtime/packages/layer-manager/use-layer-actions.mjs +5 -0
- package/runtime/plugin.d.ts +2 -0
- package/runtime/plugin.mjs +42 -0
- package/runtime/plugins/device.d.ts +136 -0
- package/runtime/plugins/device.mjs +29 -0
- package/runtime/plugins/otp-input.d.ts +2 -0
- package/runtime/plugins/otp-input.mjs +5 -0
- package/runtime/plugins/sanitize-html.d.ts +2 -0
- package/runtime/plugins/sanitize-html.mjs +90 -0
- package/runtime/plugins/sanitize-url.d.ts +2 -0
- package/runtime/plugins/sanitize-url.mjs +9 -0
- package/runtime/server/middleware/basic-auth.d.ts +2 -0
- package/runtime/server/middleware/basic-auth.mjs +34 -0
- package/runtime/thirdparty/helpers/index.d.mts +5 -0
- package/runtime/thirdparty/helpers/index.d.ts +7 -0
- package/runtime/thirdparty/helpers/index.mjs +69 -0
- package/runtime/thirdparty/helpers/index.mjs.map +1 -0
- package/runtime/thirdparty/sanitize-url/index.d.mts +2 -0
- package/runtime/thirdparty/sanitize-url/index.d.ts +1 -0
- package/runtime/thirdparty/sanitize-url/index.mjs +98 -0
- package/runtime/thirdparty/sanitize-url/index.mjs.map +1 -0
- package/runtime/ui/varlet.d.ts +7 -0
- package/runtime/ui/varlet.mjs +13 -0
- package/types.d.mts +16 -0
- package/types.d.ts +16 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { onMounted, ref, resolveComponent } from "vue"
|
|
3
|
+
import type { ActiveLayer } from "./types"
|
|
4
|
+
|
|
5
|
+
const props = defineProps<{ layer: ActiveLayer }>()
|
|
6
|
+
const emit = defineEmits(["closeLayer", "closeAllLayers"])
|
|
7
|
+
const layerRef = ref<HTMLElement | null>(null)
|
|
8
|
+
|
|
9
|
+
const closeLayer = () => emit("closeLayer", props.layer.layerId)
|
|
10
|
+
const closeAllLayers = () => emit("closeAllLayers")
|
|
11
|
+
|
|
12
|
+
onMounted(() => {
|
|
13
|
+
// eslint-disable-next-line vue/no-mutating-props
|
|
14
|
+
props.layer.closeLayer = () => closeLayer()
|
|
15
|
+
|
|
16
|
+
setTimeout(() => {
|
|
17
|
+
layerRef.value?.classList.add("open")
|
|
18
|
+
const layoutElement = document.querySelector("#layout")
|
|
19
|
+
if (layoutElement) {
|
|
20
|
+
layoutElement.classList.remove("layer-hide")
|
|
21
|
+
layoutElement.classList.add("layer-open")
|
|
22
|
+
document.documentElement.style.overflow = "hidden auto"
|
|
23
|
+
document.body.style.overflow = "hidden auto"
|
|
24
|
+
}
|
|
25
|
+
}, 50)
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const component = resolveComponent(props.layer.component)
|
|
29
|
+
if (typeof component === "string") {
|
|
30
|
+
closeLayer()
|
|
31
|
+
}
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<template>
|
|
35
|
+
<article
|
|
36
|
+
v-if="typeof component !== 'string'"
|
|
37
|
+
:id="layer.layerId"
|
|
38
|
+
ref="layerRef"
|
|
39
|
+
class="layer"
|
|
40
|
+
:data-layer="layer.name"
|
|
41
|
+
>
|
|
42
|
+
<button
|
|
43
|
+
type="button"
|
|
44
|
+
class="layer-close"
|
|
45
|
+
@click="closeLayer"
|
|
46
|
+
/>
|
|
47
|
+
<component
|
|
48
|
+
:is="component"
|
|
49
|
+
:search-params="layer.searchParams"
|
|
50
|
+
@close-layer="closeLayer"
|
|
51
|
+
@close-all-layers="closeAllLayers"
|
|
52
|
+
/>
|
|
53
|
+
</article>
|
|
54
|
+
</template>
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, onMounted, ref, watch } from "vue"
|
|
3
|
+
import { useRoute, useRouter } from "vue-router"
|
|
4
|
+
import LayerComponent from "./LayerComponent.vue"
|
|
5
|
+
import { useLayerActions } from "./use-layer-actions"
|
|
6
|
+
import type { ActiveLayer } from "./types"
|
|
7
|
+
|
|
8
|
+
const router = useRouter()
|
|
9
|
+
const route = useRoute()
|
|
10
|
+
const layerActions = useLayerActions()
|
|
11
|
+
const reactiveHistory = computed(() => ({ path: route.path, query: route.query }))
|
|
12
|
+
const history = ref({ path: route.path, query: route.query })
|
|
13
|
+
const activeLayers = ref<ActiveLayer[]>([])
|
|
14
|
+
const pageTitle = ref("")
|
|
15
|
+
const layersLimit = 5
|
|
16
|
+
|
|
17
|
+
function getLayerHash(s: string): string {
|
|
18
|
+
const hash = s.split("").reduce((a, b) => {
|
|
19
|
+
a = (a << 5) - a + b.charCodeAt(0)
|
|
20
|
+
return a & a
|
|
21
|
+
}, 0)
|
|
22
|
+
return Math.abs(hash).toString()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const createLayer = (name: string): ActiveLayer => {
|
|
26
|
+
return {
|
|
27
|
+
name,
|
|
28
|
+
layerId: getLayerHash(name),
|
|
29
|
+
component: name.charAt(0).toUpperCase() + name.slice(1),
|
|
30
|
+
searchParams: history.value.query || {},
|
|
31
|
+
closeLayer: typeof window !== "undefined" ? () => {} : undefined,
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const resolveLayer = (layerName: string, options: { isCloseOtherLayers: boolean } = { isCloseOtherLayers: false }) => {
|
|
36
|
+
const activeLayer = activeLayers.value.find(({ name }) => name === layerName)
|
|
37
|
+
if (activeLayer) {
|
|
38
|
+
// слой с таким именем уже есть
|
|
39
|
+
const layer = activeLayers.value.splice(activeLayers.value.indexOf(activeLayer), 1)[0]
|
|
40
|
+
if (layer) {
|
|
41
|
+
activeLayers.value.push(layer)
|
|
42
|
+
}
|
|
43
|
+
} else {
|
|
44
|
+
if (options.isCloseOtherLayers) {
|
|
45
|
+
activeLayers.value = []
|
|
46
|
+
}
|
|
47
|
+
if (activeLayers.value.length >= layersLimit) {
|
|
48
|
+
activeLayers.value.shift()
|
|
49
|
+
}
|
|
50
|
+
activeLayers.value.push(createLayer(layerName))
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const closeLayer = (layerId: string) => {
|
|
55
|
+
if (typeof document !== "undefined") {
|
|
56
|
+
// eslint-disable-next-line unicorn/prefer-query-selector
|
|
57
|
+
const layerElement = document.getElementById(layerId)
|
|
58
|
+
if (layerElement) {
|
|
59
|
+
layerElement.classList.remove("open")
|
|
60
|
+
layerElement.classList.add("hide")
|
|
61
|
+
}
|
|
62
|
+
const layoutElement = document.querySelector("#layout")
|
|
63
|
+
if (layoutElement) {
|
|
64
|
+
layoutElement.classList.remove("layer-open")
|
|
65
|
+
layoutElement.classList.add("layer-hide")
|
|
66
|
+
document.documentElement.style.removeProperty("overflow")
|
|
67
|
+
document.body.style.removeProperty("overflow")
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
setTimeout(() => {
|
|
72
|
+
if (!activeLayers.value.some(s => s.layerId === layerId)) {
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
activeLayers.value = activeLayers.value.filter(s => s.layerId !== layerId)
|
|
77
|
+
|
|
78
|
+
const layer = activeLayers.value.at(-1)
|
|
79
|
+
const queryLayer = layer ? { layer: layer.name, ...layer.searchParams } : {}
|
|
80
|
+
const query = { ...(history.value.query?.layer ? queryLayer : {}) }
|
|
81
|
+
|
|
82
|
+
router.push({ path: history.value.path, query })
|
|
83
|
+
if (activeLayers.value.length === 0 && typeof document !== "undefined") {
|
|
84
|
+
document.title = pageTitle.value
|
|
85
|
+
}
|
|
86
|
+
}, 400)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const closeAllLayers = () => {
|
|
90
|
+
activeLayers.value = []
|
|
91
|
+
router.push(history.value.path)
|
|
92
|
+
document.title = pageTitle.value
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
watch(reactiveHistory, (value, prevValue) => {
|
|
96
|
+
history.value = value
|
|
97
|
+
if (value.path !== prevValue.path) {
|
|
98
|
+
if (value.query.layer) {
|
|
99
|
+
resolveLayer(value.query.layer.toString(), { isCloseOtherLayers: true })
|
|
100
|
+
} else if (activeLayers.value.length > 0) {
|
|
101
|
+
activeLayers.value = []
|
|
102
|
+
document.title = pageTitle.value
|
|
103
|
+
}
|
|
104
|
+
} else if (value.query.layer) {
|
|
105
|
+
if (value.query.layer !== prevValue.query.layer) {
|
|
106
|
+
resolveLayer(value.query.layer.toString())
|
|
107
|
+
} else {
|
|
108
|
+
const activeLayer = activeLayers.value.find(({ name }) => name === value.query.layer)
|
|
109
|
+
if (activeLayer) {
|
|
110
|
+
activeLayer.searchParams = value.query
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
} else if (activeLayers.value.length > 0) {
|
|
114
|
+
activeLayers.value = []
|
|
115
|
+
document.title = pageTitle.value
|
|
116
|
+
}
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
onMounted(() => {
|
|
120
|
+
pageTitle.value = document.title
|
|
121
|
+
|
|
122
|
+
layerActions.value = {
|
|
123
|
+
initialized: true,
|
|
124
|
+
open: (layerName: string, params?: { [p: string]: any }) => {
|
|
125
|
+
router.push({ path: history.value.path, query: { layer: layerName, ...(params ?? {}) } })
|
|
126
|
+
},
|
|
127
|
+
getLayer: (layerName: string) => {
|
|
128
|
+
return activeLayers.value.find(({ name }) => name === layerName)
|
|
129
|
+
},
|
|
130
|
+
closeAllLayers: () => {
|
|
131
|
+
closeAllLayers()
|
|
132
|
+
},
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
window.addEventListener("keyup", event => {
|
|
136
|
+
if (event.key === "Escape") {
|
|
137
|
+
const lastLayer = activeLayers.value.at(-1)
|
|
138
|
+
if (lastLayer) {
|
|
139
|
+
closeLayer(lastLayer.layerId)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
if (!layerActions.value?.initialized && history.value.query?.layer) {
|
|
146
|
+
resolveLayer(history.value.query.layer.toString())
|
|
147
|
+
}
|
|
148
|
+
</script>
|
|
149
|
+
|
|
150
|
+
<script lang="ts">
|
|
151
|
+
export const useLayerManager = () => {
|
|
152
|
+
const layerActions = useLayerActions()
|
|
153
|
+
return {
|
|
154
|
+
open: (layerName: string, params?: { [p: string]: any }) => layerActions.value?.open?.(layerName, params),
|
|
155
|
+
getLayer: (layerName: string) => layerActions.value?.getLayer?.(layerName),
|
|
156
|
+
closeAllLayers: () => layerActions.value?.closeAllLayers?.(),
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
</script>
|
|
160
|
+
|
|
161
|
+
<template>
|
|
162
|
+
<div>
|
|
163
|
+
<LayerComponent
|
|
164
|
+
v-for="layer of activeLayers"
|
|
165
|
+
:key="layer.layerId"
|
|
166
|
+
:layer="layer"
|
|
167
|
+
@close-layer="closeLayer"
|
|
168
|
+
@close-all-layers="closeAllLayers"
|
|
169
|
+
/>
|
|
170
|
+
</div>
|
|
171
|
+
</template>
|
|
File without changes
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ActiveLayer } from "./types";
|
|
2
|
+
export declare const useLayerActions: () => import("vue").Ref<{
|
|
3
|
+
initialized: boolean;
|
|
4
|
+
open?: ((layerName: string, params?: {
|
|
5
|
+
[p: string]: any;
|
|
6
|
+
}) => void) | undefined;
|
|
7
|
+
getLayer?: ((layerName: string) => ActiveLayer | undefined) | undefined;
|
|
8
|
+
closeAllLayers?: (() => void) | undefined;
|
|
9
|
+
}, {
|
|
10
|
+
initialized: boolean;
|
|
11
|
+
open?: (layerName: string, params?: {
|
|
12
|
+
[p: string]: any;
|
|
13
|
+
}) => void;
|
|
14
|
+
getLayer?: (layerName: string) => ActiveLayer | undefined;
|
|
15
|
+
closeAllLayers?: () => void;
|
|
16
|
+
} | {
|
|
17
|
+
initialized: boolean;
|
|
18
|
+
open?: ((layerName: string, params?: {
|
|
19
|
+
[p: string]: any;
|
|
20
|
+
}) => void) | undefined;
|
|
21
|
+
getLayer?: ((layerName: string) => ActiveLayer | undefined) | undefined;
|
|
22
|
+
closeAllLayers?: (() => void) | undefined;
|
|
23
|
+
}>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { useLocalStorage } from "@vueuse/core";
|
|
2
|
+
import { addRouteMiddleware, defineNuxtPlugin } from "#app";
|
|
3
|
+
import { useRequestHeaders, useRuntimeConfig, useState } from "#imports";
|
|
4
|
+
import { fetch, getUser } from "./api/index.mjs";
|
|
5
|
+
import { authMiddleware, guestMiddleware, localeMiddleware } from "./middleware/index.mjs";
|
|
6
|
+
import { flush, setToken, setUser } from "./packages/api/api-client.mjs";
|
|
7
|
+
import bus from "./packages/api/bus.mjs";
|
|
8
|
+
const useAuth = () => {
|
|
9
|
+
return useState("auth", () => null);
|
|
10
|
+
};
|
|
11
|
+
export default defineNuxtPlugin(async (nuxtApp) => {
|
|
12
|
+
const auth = useAuth();
|
|
13
|
+
const runtimeConfig = useRuntimeConfig();
|
|
14
|
+
if (runtimeConfig.public.ssr && import.meta.server || !runtimeConfig.public.ssr) {
|
|
15
|
+
flush();
|
|
16
|
+
if (import.meta.server) {
|
|
17
|
+
auth.value = await fetch("/account/0/authcheck", {
|
|
18
|
+
baseURL: "/",
|
|
19
|
+
headers: useRequestHeaders(["cookie"])
|
|
20
|
+
});
|
|
21
|
+
} else {
|
|
22
|
+
auth.value = await getUser();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (auth.value) {
|
|
26
|
+
setToken(auth.value.token);
|
|
27
|
+
setUser(auth.value.user);
|
|
28
|
+
}
|
|
29
|
+
nuxtApp.hook("app:beforeMount", () => {
|
|
30
|
+
auth.value = null;
|
|
31
|
+
bus.subscribe("user:onUpdated", (value) => {
|
|
32
|
+
const loggedIn = useLocalStorage("lin", "no");
|
|
33
|
+
loggedIn.value = value ? "yes" : "no";
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
addRouteMiddleware("auth", authMiddleware, { global: false });
|
|
37
|
+
addRouteMiddleware("guest", guestMiddleware, { global: false });
|
|
38
|
+
addRouteMiddleware("locale", localeMiddleware, { global: true });
|
|
39
|
+
return {
|
|
40
|
+
provide: {}
|
|
41
|
+
};
|
|
42
|
+
});
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
export interface Device {
|
|
2
|
+
mobile: () => boolean;
|
|
3
|
+
tablet: () => boolean;
|
|
4
|
+
desktop: () => boolean;
|
|
5
|
+
ios: () => boolean;
|
|
6
|
+
macos: () => boolean;
|
|
7
|
+
ipad: () => boolean;
|
|
8
|
+
iphone: () => boolean;
|
|
9
|
+
ipod: () => boolean;
|
|
10
|
+
android: () => boolean;
|
|
11
|
+
androidPhone: () => boolean;
|
|
12
|
+
androidTablet: () => boolean;
|
|
13
|
+
blackberry: () => boolean;
|
|
14
|
+
blackberryPhone: () => boolean;
|
|
15
|
+
blackberryTablet: () => boolean;
|
|
16
|
+
windows: () => boolean;
|
|
17
|
+
windowsPhone: () => boolean;
|
|
18
|
+
windowsTablet: () => boolean;
|
|
19
|
+
fxos: () => boolean;
|
|
20
|
+
fxosPhone: () => boolean;
|
|
21
|
+
fxosTablet: () => boolean;
|
|
22
|
+
meego: () => boolean;
|
|
23
|
+
television: () => boolean;
|
|
24
|
+
mobileApp: () => boolean;
|
|
25
|
+
iosMobileApp: () => boolean;
|
|
26
|
+
androidMobileApp: () => boolean;
|
|
27
|
+
tabletApp: () => boolean;
|
|
28
|
+
iosTabletApp: () => boolean;
|
|
29
|
+
androidTabletApp: () => boolean;
|
|
30
|
+
landscape: () => boolean;
|
|
31
|
+
portrait: () => boolean;
|
|
32
|
+
onChangeOrientation: (cb: (newOrientation: DeviceOrientation) => void) => void;
|
|
33
|
+
noConflict: (currentDevice: Device) => void;
|
|
34
|
+
type: DeviceType;
|
|
35
|
+
orientation: DeviceOrientation;
|
|
36
|
+
os: DeviceOs;
|
|
37
|
+
osName: () => string;
|
|
38
|
+
}
|
|
39
|
+
export type DeviceType = "mobile" | "tablet" | "desktop" | "unknown";
|
|
40
|
+
export type DeviceOrientation = "landscape" | "portrait" | "unknown";
|
|
41
|
+
export type DeviceOs = "ios" | "macos" | "iphone" | "ipad" | "ipod" | "android" | "blackberry" | "windows" | "fxos" | "meego" | "television" | "unknown";
|
|
42
|
+
declare const _default: import("#app").Plugin<{
|
|
43
|
+
device: {
|
|
44
|
+
mobileApp: () => boolean;
|
|
45
|
+
iosMobileApp: () => boolean;
|
|
46
|
+
androidMobileApp: () => boolean;
|
|
47
|
+
tabletApp: () => boolean;
|
|
48
|
+
iosTabletApp: () => boolean;
|
|
49
|
+
androidTabletApp: () => boolean;
|
|
50
|
+
getInfo: () => Promise<string>;
|
|
51
|
+
mobile: () => boolean;
|
|
52
|
+
tablet: () => boolean;
|
|
53
|
+
desktop: () => boolean;
|
|
54
|
+
ios: () => boolean;
|
|
55
|
+
macos: () => boolean;
|
|
56
|
+
ipad: () => boolean;
|
|
57
|
+
iphone: () => boolean;
|
|
58
|
+
ipod: () => boolean;
|
|
59
|
+
android: () => boolean;
|
|
60
|
+
androidPhone: () => boolean;
|
|
61
|
+
androidTablet: () => boolean;
|
|
62
|
+
blackberry: () => boolean;
|
|
63
|
+
blackberryPhone: () => boolean;
|
|
64
|
+
blackberryTablet: () => boolean;
|
|
65
|
+
windows: () => boolean;
|
|
66
|
+
windowsPhone: () => boolean;
|
|
67
|
+
windowsTablet: () => boolean;
|
|
68
|
+
fxos: () => boolean;
|
|
69
|
+
fxosPhone: () => boolean;
|
|
70
|
+
fxosTablet: () => boolean;
|
|
71
|
+
meego: () => boolean;
|
|
72
|
+
television: () => boolean;
|
|
73
|
+
landscape: () => boolean;
|
|
74
|
+
portrait: () => boolean;
|
|
75
|
+
onChangeOrientation: (cb: (newOrientation: DeviceOrientation) => void) => void;
|
|
76
|
+
noConflict: (currentDevice: Device) => void;
|
|
77
|
+
type: DeviceType;
|
|
78
|
+
orientation: DeviceOrientation;
|
|
79
|
+
os: DeviceOs;
|
|
80
|
+
osName: () => string;
|
|
81
|
+
};
|
|
82
|
+
}> & import("#app").ObjectPlugin<{
|
|
83
|
+
device: {
|
|
84
|
+
mobileApp: () => boolean;
|
|
85
|
+
iosMobileApp: () => boolean;
|
|
86
|
+
androidMobileApp: () => boolean;
|
|
87
|
+
tabletApp: () => boolean;
|
|
88
|
+
iosTabletApp: () => boolean;
|
|
89
|
+
androidTabletApp: () => boolean;
|
|
90
|
+
getInfo: () => Promise<string>;
|
|
91
|
+
mobile: () => boolean;
|
|
92
|
+
tablet: () => boolean;
|
|
93
|
+
desktop: () => boolean;
|
|
94
|
+
ios: () => boolean;
|
|
95
|
+
macos: () => boolean;
|
|
96
|
+
ipad: () => boolean;
|
|
97
|
+
iphone: () => boolean;
|
|
98
|
+
ipod: () => boolean;
|
|
99
|
+
android: () => boolean;
|
|
100
|
+
androidPhone: () => boolean;
|
|
101
|
+
androidTablet: () => boolean;
|
|
102
|
+
blackberry: () => boolean;
|
|
103
|
+
blackberryPhone: () => boolean;
|
|
104
|
+
blackberryTablet: () => boolean;
|
|
105
|
+
windows: () => boolean;
|
|
106
|
+
windowsPhone: () => boolean;
|
|
107
|
+
windowsTablet: () => boolean;
|
|
108
|
+
fxos: () => boolean;
|
|
109
|
+
fxosPhone: () => boolean;
|
|
110
|
+
fxosTablet: () => boolean;
|
|
111
|
+
meego: () => boolean;
|
|
112
|
+
television: () => boolean;
|
|
113
|
+
landscape: () => boolean;
|
|
114
|
+
portrait: () => boolean;
|
|
115
|
+
onChangeOrientation: (cb: (newOrientation: DeviceOrientation) => void) => void;
|
|
116
|
+
noConflict: (currentDevice: Device) => void;
|
|
117
|
+
type: DeviceType;
|
|
118
|
+
orientation: DeviceOrientation;
|
|
119
|
+
os: DeviceOs;
|
|
120
|
+
osName: () => string;
|
|
121
|
+
};
|
|
122
|
+
}>;
|
|
123
|
+
export default _default;
|
|
124
|
+
declare module "#app" {
|
|
125
|
+
interface NuxtApp {
|
|
126
|
+
$device: Device;
|
|
127
|
+
$mobileApp: {
|
|
128
|
+
getInfo: () => Promise<{
|
|
129
|
+
name: string;
|
|
130
|
+
}>;
|
|
131
|
+
changeTheme: ({ theme }: {
|
|
132
|
+
theme: string;
|
|
133
|
+
}) => Promise<void>;
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { defineNuxtPlugin } from "#app";
|
|
2
|
+
import { useNuxtApp, useRuntimeConfig } from "#imports";
|
|
3
|
+
import { device as currentDevice } from "../packages/api/helpers/index.mjs";
|
|
4
|
+
export default defineNuxtPlugin(() => {
|
|
5
|
+
const device = currentDevice;
|
|
6
|
+
const runtimeConfig = useRuntimeConfig();
|
|
7
|
+
const isMobileApp = Boolean(runtimeConfig.public.isMobileApp);
|
|
8
|
+
return {
|
|
9
|
+
provide: {
|
|
10
|
+
device: {
|
|
11
|
+
...device,
|
|
12
|
+
mobileApp: () => isMobileApp && device.mobile(),
|
|
13
|
+
iosMobileApp: () => isMobileApp && device.mobile() && device.ios(),
|
|
14
|
+
androidMobileApp: () => isMobileApp && device.androidPhone(),
|
|
15
|
+
tabletApp: () => isMobileApp && device.tablet(),
|
|
16
|
+
iosTabletApp: () => isMobileApp && device.tablet() && device.ios(),
|
|
17
|
+
androidTabletApp: () => isMobileApp && device.androidTablet(),
|
|
18
|
+
getInfo: async () => {
|
|
19
|
+
const { $mobileApp } = useNuxtApp();
|
|
20
|
+
if (isMobileApp && $mobileApp && typeof $mobileApp.getInfo === "function") {
|
|
21
|
+
const device2 = await $mobileApp.getInfo();
|
|
22
|
+
return device2.name;
|
|
23
|
+
}
|
|
24
|
+
return device.osName();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { transform } from "ultrahtml";
|
|
2
|
+
import sanitize from "ultrahtml/transformers/sanitize";
|
|
3
|
+
import { defineNuxtPlugin } from "#app";
|
|
4
|
+
export default defineNuxtPlugin((nuxtApp) => {
|
|
5
|
+
nuxtApp.vueApp.directive("sanitize-html", async (el, binding) => {
|
|
6
|
+
if (binding.value !== binding.oldValue) {
|
|
7
|
+
el.innerHTML = await transform(binding.value, [
|
|
8
|
+
sanitize({
|
|
9
|
+
allowElements: [
|
|
10
|
+
"address",
|
|
11
|
+
"article",
|
|
12
|
+
"aside",
|
|
13
|
+
"footer",
|
|
14
|
+
"header",
|
|
15
|
+
"h1",
|
|
16
|
+
"h2",
|
|
17
|
+
"h3",
|
|
18
|
+
"h4",
|
|
19
|
+
"h5",
|
|
20
|
+
"h6",
|
|
21
|
+
"hgroup",
|
|
22
|
+
"main",
|
|
23
|
+
"nav",
|
|
24
|
+
"section",
|
|
25
|
+
"blockquote",
|
|
26
|
+
"dd",
|
|
27
|
+
"div",
|
|
28
|
+
"dl",
|
|
29
|
+
"dt",
|
|
30
|
+
"figcaption",
|
|
31
|
+
"figure",
|
|
32
|
+
"hr",
|
|
33
|
+
"li",
|
|
34
|
+
"main",
|
|
35
|
+
"ol",
|
|
36
|
+
"p",
|
|
37
|
+
"pre",
|
|
38
|
+
"ul",
|
|
39
|
+
"a",
|
|
40
|
+
"abbr",
|
|
41
|
+
"b",
|
|
42
|
+
"bdi",
|
|
43
|
+
"bdo",
|
|
44
|
+
"br",
|
|
45
|
+
"cite",
|
|
46
|
+
"code",
|
|
47
|
+
"data",
|
|
48
|
+
"dfn",
|
|
49
|
+
"em",
|
|
50
|
+
"i",
|
|
51
|
+
"kbd",
|
|
52
|
+
"mark",
|
|
53
|
+
"q",
|
|
54
|
+
"rb",
|
|
55
|
+
"rp",
|
|
56
|
+
"rt",
|
|
57
|
+
"rtc",
|
|
58
|
+
"ruby",
|
|
59
|
+
"s",
|
|
60
|
+
"samp",
|
|
61
|
+
"small",
|
|
62
|
+
"span",
|
|
63
|
+
"strong",
|
|
64
|
+
"sub",
|
|
65
|
+
"sup",
|
|
66
|
+
"time",
|
|
67
|
+
"u",
|
|
68
|
+
"var",
|
|
69
|
+
"wbr",
|
|
70
|
+
"caption",
|
|
71
|
+
"col",
|
|
72
|
+
"colgroup",
|
|
73
|
+
"table",
|
|
74
|
+
"tbody",
|
|
75
|
+
"td",
|
|
76
|
+
"tfoot",
|
|
77
|
+
"th",
|
|
78
|
+
"thead",
|
|
79
|
+
"tr",
|
|
80
|
+
"img"
|
|
81
|
+
],
|
|
82
|
+
allowAttributes: {
|
|
83
|
+
a: ["href", "name", "target"],
|
|
84
|
+
img: ["src", "srcset", "alt", "title", "width", "height", "loading"]
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
]);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { defineNuxtPlugin } from "#app";
|
|
2
|
+
import { sanitizeUrl } from "../thirdparty/sanitize-url/index.mjs";
|
|
3
|
+
export default defineNuxtPlugin((nuxtApp) => {
|
|
4
|
+
nuxtApp.vueApp.directive("sanitize-url", (el, binding) => {
|
|
5
|
+
if (binding.value !== binding.oldValue) {
|
|
6
|
+
el.href = sanitizeUrl(binding.value);
|
|
7
|
+
}
|
|
8
|
+
});
|
|
9
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Buffer } from "node:buffer";
|
|
2
|
+
import { defineEventHandler } from "h3";
|
|
3
|
+
import { useRuntimeConfig } from "#imports";
|
|
4
|
+
export default defineEventHandler((event) => {
|
|
5
|
+
let basicAuthEnabled = false;
|
|
6
|
+
let basicAuthUsers;
|
|
7
|
+
if (import.meta.server) {
|
|
8
|
+
basicAuthEnabled = useRuntimeConfig().basicAuthEnabled ?? false;
|
|
9
|
+
basicAuthUsers = useRuntimeConfig().basicAuthUsers ?? [];
|
|
10
|
+
}
|
|
11
|
+
const config = {
|
|
12
|
+
enabled: basicAuthEnabled,
|
|
13
|
+
users: basicAuthUsers ?? "",
|
|
14
|
+
deniedRoutes: ["/", "/en", "/ru"]
|
|
15
|
+
};
|
|
16
|
+
if (!config.enabled || !config.users?.length || !config.deniedRoutes.includes(event.node.req?.url ?? "")) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
let authenticated = false;
|
|
20
|
+
const credentials = event.node.req.headers?.authorization?.split(" ")[1];
|
|
21
|
+
if (credentials) {
|
|
22
|
+
const [username, password] = Buffer.from(credentials, "base64").toString("ascii").split(":");
|
|
23
|
+
const users = Array.isArray(config.users) ? config.users : config.users.split(",").map((user) => {
|
|
24
|
+
const [username2, password2] = user.split(":");
|
|
25
|
+
return { username: username2, password: password2 };
|
|
26
|
+
});
|
|
27
|
+
authenticated = users.some((user) => user.username === username && user.password === password);
|
|
28
|
+
}
|
|
29
|
+
if (!authenticated) {
|
|
30
|
+
event.node.res.setHeader("WWW-Authenticate", "Basic realm='Secure Area'");
|
|
31
|
+
event.node.res.statusCode = 401;
|
|
32
|
+
event.node.res.end("Access denied");
|
|
33
|
+
}
|
|
34
|
+
});
|