Change ads provider, and add consent system for advertising (#155)
* Add GAM integration & base for GPDR consent * Moved consent to a specific page. * Added functionality to the privacy page, and desactivate tracking if consent is not given. * Added GeoEdge support, and fixed auth issues * Fix actions issue * Fix actions issue, attempt 2 * Added a module for analytics with consent support. * Remove unnecessary function * Add support for runtime config
This commit is contained in:
parent
103ce44ba9
commit
03b2d02742
3
.eslintignore
Normal file
3
.eslintignore
Normal file
@ -0,0 +1,3 @@
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
modules/*
|
||||
@ -420,3 +420,56 @@
|
||||
}
|
||||
}
|
||||
|
||||
.switch {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
cursor: pointer;
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.stylized-toggle {
|
||||
height: 32px;
|
||||
width: 52px;
|
||||
border-radius: 16px;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
margin: 0;
|
||||
border: 2px solid var(--color-button-bg);
|
||||
transition: all .2s ease;
|
||||
background: var(--color-button-bg);
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
background: white;
|
||||
box-shadow: 0 1px 2px rgba(44,44,44,.2);
|
||||
transition: all .2s cubic-bezier(.5,.1,.75,1.35);
|
||||
}
|
||||
&:checked {
|
||||
background: var(--color-brand);
|
||||
border: 2px solid var(--color-brand);
|
||||
&:after {
|
||||
transform: translatex(20px);
|
||||
}
|
||||
}
|
||||
&:hover &:focus {
|
||||
background: var(--color-button-bg);
|
||||
border: 2px solid var(--color-button-bg);
|
||||
}
|
||||
&:hover:checked &:focus:checked {
|
||||
background: var(--color-brand);
|
||||
border: 2px solid var(--color-brand);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,25 +1,23 @@
|
||||
<template>
|
||||
<div class="ad-wrapper">
|
||||
<adsbygoogle
|
||||
ad-slot="7510690716"
|
||||
:ad-format="format"
|
||||
:page-url="pageUrl ? pageUrl : undefined"
|
||||
/>
|
||||
<div class="ad">
|
||||
<GptAd :ad-unit="adUnit" :size="size" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/* eslint-disable no-undef */
|
||||
export default {
|
||||
name: 'Advertisement',
|
||||
props: {
|
||||
format: {
|
||||
size: {
|
||||
type: String,
|
||||
default: 'horizontal',
|
||||
required: true,
|
||||
},
|
||||
pageUrl: {
|
||||
adUnit: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -29,6 +27,9 @@ export default {
|
||||
.ad-wrapper {
|
||||
width: 100%;
|
||||
@extend %card;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-bottom: var(--spacing-card-md);
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
77
components/ads/CookieConsent.vue
Normal file
77
components/ads/CookieConsent.vue
Normal file
@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<div>
|
||||
<ReviewPopup ref="popup" />
|
||||
<div
|
||||
ref="container"
|
||||
class="container"
|
||||
:style="{ visibility: shown ? 'visible' : 'hidden' }"
|
||||
>
|
||||
<div class="banner">
|
||||
<span>
|
||||
Modrinth uses cookies for various purposes, including advertising.<br />
|
||||
We encourage you to review your privacy settings by clicking on the
|
||||
button below:
|
||||
</span>
|
||||
<div class="actions">
|
||||
<button class="btn button" @click="hide">Accept all</button>
|
||||
<button class="btn brand-button" @click="review">Review</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'CookieConsent',
|
||||
data() {
|
||||
return {
|
||||
shown: false,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// Get informations in the store
|
||||
this.$store.dispatch('consent/loadFromCookies', this.$cookies)
|
||||
if (
|
||||
!this.$store.state.consent.is_consent_given &&
|
||||
this.$route.path !== '/dashboard/privacy'
|
||||
) {
|
||||
this.shown = true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
hide() {
|
||||
this.shown = false
|
||||
},
|
||||
review() {
|
||||
this.hide()
|
||||
this.$router.push('/dashboard/privacy')
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
z-index: 20;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
.banner {
|
||||
@extend %card;
|
||||
margin: 0 2rem 2rem 0;
|
||||
padding: 1rem;
|
||||
max-width: 18vw;
|
||||
border-left: solid 5px var(--color-brand);
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-top: 1rem;
|
||||
.btn {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
24
components/ads/ReviewPopup.vue
Normal file
24
components/ads/ReviewPopup.vue
Normal file
@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<Popup :show-popup="shown"> </Popup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ReviewPopup',
|
||||
data() {
|
||||
return {
|
||||
shown: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
show() {
|
||||
this.shown = true
|
||||
},
|
||||
hide() {
|
||||
this.shown = false
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -26,6 +26,11 @@
|
||||
<a target="_blank" href="https://twitter.com/modrinth">Twitter</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<nuxt-link to="/dashboard/privacy">Set privacy preferences</nuxt-link>
|
||||
</li>
|
||||
</ul>
|
||||
<span> © Guavy LLC </span><br />
|
||||
<span v-if="version !== 'unknown'">Version: {{ version }}</span>
|
||||
</footer>
|
||||
|
||||
@ -65,9 +65,8 @@
|
||||
</div>
|
||||
<Advertisement
|
||||
v-if="mod.status === 'approved' || mod.status === 'unlisted'"
|
||||
:page-url="
|
||||
'https://modrinth.com/mod/' + (mod.slug ? mod.slug : mod.id)
|
||||
"
|
||||
ad-unit="banner"
|
||||
size="728x90,468x60"
|
||||
/>
|
||||
<div class="mod-navigation">
|
||||
<div class="tabs">
|
||||
@ -133,9 +132,8 @@
|
||||
<slot />
|
||||
<Advertisement
|
||||
v-if="mod.status === 'approved' || mod.status === 'unlisted'"
|
||||
:page-url="
|
||||
'https://modrinth.com/mod/' + (mod.slug ? mod.slug : mod.id)
|
||||
"
|
||||
ad-unit="banner"
|
||||
size="728x90,468x60"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -333,10 +331,8 @@
|
||||
</div>
|
||||
<Advertisement
|
||||
v-if="mod.status === 'approved' || mod.status === 'unlisted'"
|
||||
format="rectangle"
|
||||
:page-url="
|
||||
'https://modrinth.com/mod/' + (mod.slug ? mod.slug : mod.id)
|
||||
"
|
||||
ad-unit="square"
|
||||
size="250x250,200x200"
|
||||
/>
|
||||
<m-footer class="footer" />
|
||||
</section>
|
||||
@ -364,7 +360,7 @@ import ExternalIcon from '~/assets/images/utils/external.svg?inline'
|
||||
|
||||
import ForgeIcon from '~/assets/images/categories/forge.svg?inline'
|
||||
import FabricIcon from '~/assets/images/categories/fabric.svg?inline'
|
||||
import Advertisement from '~/components/Advertisement'
|
||||
import Advertisement from '~/components/ads/Advertisement'
|
||||
|
||||
export default {
|
||||
name: 'ModPage',
|
||||
|
||||
@ -23,7 +23,7 @@ export default {
|
||||
.popup-overlay {
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
z-index: 10;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@ -38,11 +38,11 @@ export default {
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 2;
|
||||
z-index: 11;
|
||||
box-shadow: 0 2px 3px 1px var(--color-button-bg);
|
||||
border-radius: 10px;
|
||||
max-height: 80%;
|
||||
overflow-y: auto;
|
||||
background-color: var(--color-bg);
|
||||
background-color: var(--color-raised-bg);
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -96,6 +96,7 @@
|
||||
</section>
|
||||
</header>
|
||||
<main>
|
||||
<CookieConsent />
|
||||
<notifications group="main" position="bottom right" />
|
||||
<!--<notifications
|
||||
group="ads"
|
||||
|
||||
8
middleware/ads_tracking.js
Normal file
8
middleware/ads_tracking.js
Normal file
@ -0,0 +1,8 @@
|
||||
/* eslint-disable no-undef */
|
||||
export default function ({ route }) {
|
||||
if (process.client) {
|
||||
googletag.cmd.push(function () {
|
||||
googletag.pubads().setTargeting('path', route.path)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,9 @@ export default async function (context) {
|
||||
context.app.$cookies.set('auth-token', context.route.query.code, {
|
||||
secure: true,
|
||||
sameSite: 'Strict',
|
||||
maxAge: 60 * 60 * 2, // 2 hours
|
||||
httpOnly: true,
|
||||
path: '/',
|
||||
})
|
||||
|
||||
await context.store.dispatch('auth/fetchUser', {
|
||||
|
||||
6
modules/analytics/lib/constants.js
Normal file
6
modules/analytics/lib/constants.js
Normal file
@ -0,0 +1,6 @@
|
||||
export const DEFAULT_OPTIONS = {
|
||||
enabled: false,
|
||||
script_url: 'https://example.com',
|
||||
tracking_code: 'xxx'
|
||||
}
|
||||
export const UNAMI_LIB_TAG_ID = 'unami-import'
|
||||
22
modules/analytics/lib/module.js
Normal file
22
modules/analytics/lib/module.js
Normal file
@ -0,0 +1,22 @@
|
||||
import {
|
||||
DEFAULT_OPTIONS,
|
||||
UNAMI_LIB_TAG_ID
|
||||
} from './constants';
|
||||
|
||||
const { resolve } = require('path');
|
||||
|
||||
module.exports = async function module(moduleOptions) {
|
||||
const options = Object.assign(DEFAULT_OPTIONS, this.options.analytics, moduleOptions);
|
||||
|
||||
const templatesOptions = {
|
||||
...options,
|
||||
UNAMI_LIB_TAG_ID
|
||||
};
|
||||
|
||||
this.addPlugin({
|
||||
src: resolve(__dirname, 'templates/plugin.js'),
|
||||
fileName: 'analytics/plugin.js',
|
||||
options: templatesOptions,
|
||||
});
|
||||
};
|
||||
module.exports.meta = require('../package.json');
|
||||
64
modules/analytics/lib/templates/plugin.js
Normal file
64
modules/analytics/lib/templates/plugin.js
Normal file
@ -0,0 +1,64 @@
|
||||
import Vue from 'vue';
|
||||
|
||||
function isAnalyticsOn(ctx) {
|
||||
let cookies = null
|
||||
if (ctx.req != null) {
|
||||
//Server side rendering
|
||||
cookies = ctx.req.headers.cookie;
|
||||
} else {
|
||||
// Rely on the client
|
||||
cookies = document.cookie;
|
||||
}
|
||||
let processed = {}
|
||||
cookies.split(';').forEach((e) => {
|
||||
let val = e.trim().split('=');
|
||||
processed[val[0]] = decodeURI(val[1]);
|
||||
})
|
||||
let scopes = decodeURIComponent(processed['modrinth-scopes']).split(",");
|
||||
return (scopes !== null && scopes.includes('analytics'));
|
||||
}
|
||||
|
||||
export default async function (ctx, inject) {
|
||||
|
||||
const { app } = ctx;
|
||||
const config = ctx.$config && ctx.$config.analytics || {};
|
||||
|
||||
const url = config.script_url ?? '<%= options.script_url %>';
|
||||
const tag = config.tracking_code ?? '<%= options.tracking_code %>';
|
||||
const enabled = config.enabled ?? <%= options.enabled || false %>;
|
||||
// Check if the parameters are not changed by runtime config:
|
||||
|
||||
|
||||
|
||||
const UNAMI_LIB_TAG_ID = '<%= options.UNAMI_LIB_TAG_ID %>';
|
||||
|
||||
|
||||
if (!enabled) {
|
||||
console.log("Analytics are not enabled.")
|
||||
return;
|
||||
}
|
||||
|
||||
const injectScript = (script) => {
|
||||
const scriptIndex = ctx.app.head.script.findIndex(s => s.hid === script.hid);
|
||||
if (scriptIndex !== -1) {
|
||||
ctx.app.head.script[scriptIndex] = script;
|
||||
} else {
|
||||
ctx.app.head.script.push(script);
|
||||
}
|
||||
};
|
||||
if (isAnalyticsOn(ctx)) {
|
||||
// Inject unami
|
||||
const analyticsScript = {
|
||||
hid: UNAMI_LIB_TAG_ID,
|
||||
src: url,
|
||||
'data-website-id': 'c37613de-245d-4767-90e7-ba7980a4f1a2',
|
||||
async: true,
|
||||
defer: true,
|
||||
};
|
||||
injectScript(analyticsScript);
|
||||
} else {
|
||||
// console.log("Analytics scope was denied.")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
31
modules/analytics/package.json
Normal file
31
modules/analytics/package.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "@modrinth/analytics",
|
||||
"version": "0.1.0",
|
||||
"description": "Unami integration for Nuxtjs",
|
||||
"license": "MIT",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "redblueflame <contact@redblueflame.com>"
|
||||
}
|
||||
],
|
||||
"main": "lib/module.js",
|
||||
"repository": "https://github.com/modrinth/knossos/",
|
||||
"homepage": "https://github.com/modrinth/knossos/tree/master/modules/analytics",
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"devDependencies": {
|
||||
"codecov": "latest",
|
||||
"eslint": "5.13.0",
|
||||
"eslint-config-airbnb-base": "13.1.0",
|
||||
"eslint-loader": "2.1.2",
|
||||
"eslint-plugin-import": "2.16.0",
|
||||
"eslint-plugin-jest": "22.3.0",
|
||||
"eslint-plugin-vue": "5.2.1",
|
||||
"jest": "24.1.0",
|
||||
"jsdom": "14.0.0",
|
||||
"nuxt": "2.4.3",
|
||||
"request-promise-native": "1.0.5",
|
||||
"standard-version": "latest"
|
||||
}
|
||||
}
|
||||
16
modules/gpt-ads/lib/constants.js
Normal file
16
modules/gpt-ads/lib/constants.js
Normal file
@ -0,0 +1,16 @@
|
||||
export const DEFAULT_OPTIONS = {
|
||||
networkCode: null,
|
||||
debug: false,
|
||||
ghostMode: false,
|
||||
componentName: 'GptAd',
|
||||
individualRefresh: false,
|
||||
responsive: false,
|
||||
collapseEmptyDivs: false,
|
||||
emptyClass: 'is-empty',
|
||||
geoEdgeId: ''
|
||||
};
|
||||
|
||||
export const GPT_LIB_SCRIPT_ID = 'google-publisher-tag-lib-script';
|
||||
export const GPT_INIT_SCRIPT_ID = 'google-publisher-tag-init-script';
|
||||
export const GEOEDGE_CONF_SCRIPT_ID = 'geoedge-config-script';
|
||||
export const GEOEDGE_LIB_SCRIPT_ID = 'geoedge-lib-script';
|
||||
34
modules/gpt-ads/lib/module.js
Normal file
34
modules/gpt-ads/lib/module.js
Normal file
@ -0,0 +1,34 @@
|
||||
import {
|
||||
DEFAULT_OPTIONS,
|
||||
GPT_LIB_SCRIPT_ID,
|
||||
GPT_INIT_SCRIPT_ID,
|
||||
GEOEDGE_CONF_SCRIPT_ID,
|
||||
GEOEDGE_LIB_SCRIPT_ID,
|
||||
} from './constants';
|
||||
|
||||
const { resolve } = require('path');
|
||||
|
||||
module.exports = async function module(moduleOptions) {
|
||||
const options = Object.assign(DEFAULT_OPTIONS, this.options.ads, moduleOptions);
|
||||
|
||||
const templatesOptions = {
|
||||
...options,
|
||||
GPT_LIB_SCRIPT_ID,
|
||||
GPT_INIT_SCRIPT_ID,
|
||||
GEOEDGE_CONF_SCRIPT_ID,
|
||||
GEOEDGE_LIB_SCRIPT_ID,
|
||||
};
|
||||
|
||||
this.addPlugin({
|
||||
src: resolve(__dirname, 'templates/plugin.js'),
|
||||
fileName: 'gpt-ads-module/plugin.js',
|
||||
options: templatesOptions,
|
||||
});
|
||||
|
||||
this.addTemplate({
|
||||
src: resolve(__dirname, 'templates/component.js'),
|
||||
fileName: 'gpt-ads-module/component.js',
|
||||
options: templatesOptions,
|
||||
});
|
||||
};
|
||||
module.exports.meta = require('../package.json');
|
||||
256
modules/gpt-ads/lib/templates/component.js
Normal file
256
modules/gpt-ads/lib/templates/component.js
Normal file
@ -0,0 +1,256 @@
|
||||
export default {
|
||||
name: '<%= options.componentName %>',
|
||||
data: () => ({
|
||||
adSlot: null,
|
||||
mapping: [],
|
||||
currentSizeMappingIndex: null,
|
||||
windowResizeListenerDebounce: null,
|
||||
isEmpty: true,
|
||||
}),
|
||||
props: {
|
||||
adUnit: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
size: {
|
||||
type: [Array, String],
|
||||
required: true,
|
||||
},
|
||||
sizeMapping: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
id: {
|
||||
type: [Number, String],
|
||||
required: false,
|
||||
default: () => Math.random().toString(36).substring(5),
|
||||
},
|
||||
isResponsive: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: <%= options.responsive %>,
|
||||
},
|
||||
windowResizeDebounce: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 300,
|
||||
},
|
||||
collapseEmptyDiv: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
ghostMode() {
|
||||
return this.$config.ads.ghostMode ?? <%= options.ghostMode %>;
|
||||
},
|
||||
networkCode() {
|
||||
const { $gptAds } = this;
|
||||
return $gptAds ? $gptAds.networkCode : null;
|
||||
},
|
||||
adUnitPath() {
|
||||
const { networkCode, adUnit } = this;
|
||||
return `/${networkCode}/${adUnit}`;
|
||||
},
|
||||
divId() {
|
||||
const { id } = this;
|
||||
return `div-gpt-ad-${id}-0`;
|
||||
},
|
||||
formattedSize() {
|
||||
return this.formatSizeList(this.size);
|
||||
},
|
||||
style() {
|
||||
if (this.ghostMode) {
|
||||
const { formattedSize, currentSizeMappingIndex, mapping } = this;
|
||||
let baseSize = formattedSize;
|
||||
if (currentSizeMappingIndex !== null) {
|
||||
baseSize = mapping[currentSizeMappingIndex][1];
|
||||
}
|
||||
const size = Array.isArray(baseSize[0]) ? baseSize[0] : [baseSize[0], baseSize[1]];
|
||||
const [width, height] = size;
|
||||
return {
|
||||
margin: '0 auto',
|
||||
width: `${width}px`,
|
||||
height: `${height}px`,
|
||||
border: '1px solid black',
|
||||
};
|
||||
}
|
||||
return null;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Formats a given size to make it compatible with GPT
|
||||
* If size is an Array, it is returned as is
|
||||
* If size is a string, it is formatted so that 123x456 becomes [123, 456]
|
||||
*
|
||||
* @param {Array,string} size The size
|
||||
* @return {Array} Formatted size
|
||||
*/
|
||||
formatSize(size) {
|
||||
if (Array.isArray(size)) {
|
||||
return size;
|
||||
}
|
||||
if (typeof size === 'string') {
|
||||
return size.split('x').map(value => parseInt(value, 10));
|
||||
}
|
||||
return [];
|
||||
},
|
||||
/**
|
||||
* Formats a given list of sizes to make it compatible with GPT API
|
||||
* If sizesList is an Array, it is returned as is
|
||||
* If sizesList is a string, it is formatted so that
|
||||
* 123x456,654x321 becomes [[123, 456], [654, 321]]
|
||||
*
|
||||
* @param {Array,string} sizesList The sizes
|
||||
* @return {Array} Formatted sizes list
|
||||
*/
|
||||
formatSizeList(sizesList) {
|
||||
if (Array.isArray(sizesList)) {
|
||||
return sizesList;
|
||||
}
|
||||
if (typeof sizesList === 'string') {
|
||||
return sizesList
|
||||
.split(',')
|
||||
.map(size => this.formatSize(size));
|
||||
}
|
||||
return [];
|
||||
},
|
||||
/**
|
||||
* Refresh ad slot
|
||||
*/
|
||||
refreshSlot() {
|
||||
googletag.pubads().refresh([this.adSlot]);
|
||||
},
|
||||
handleSlotRenderEnded (event) {
|
||||
if (event.slot.getSlotId().getDomId() !== this.divId) {
|
||||
return;
|
||||
}
|
||||
this.isEmpty = !!event.isEmpty;
|
||||
},
|
||||
/**
|
||||
* Window resize event listener
|
||||
* Attached only when responsive mode is enabled, it checks wether a different size
|
||||
* mapping can be activated after resize and forces the slot to be refreshed if it's
|
||||
* the case
|
||||
*/
|
||||
handleWindowResize() {
|
||||
const { windowResizeDebounce } = this;
|
||||
clearTimeout(this.windowResizeListenerDebounce);
|
||||
this.windowResizeListenerDebounce = setTimeout(() => {
|
||||
const currentSizeMappingIndex = this.getCurrentSizeMappingIndex();
|
||||
if (currentSizeMappingIndex !== this.currentSizeMappingIndex) {
|
||||
if (!this.ghostMode) {
|
||||
this.refreshSlot();
|
||||
}
|
||||
this.currentSizeMappingIndex = currentSizeMappingIndex;
|
||||
}
|
||||
}, windowResizeDebounce);
|
||||
},
|
||||
/**
|
||||
* Gets the current size mapping index
|
||||
*
|
||||
* @return {Number} The current size mapping index
|
||||
*/
|
||||
getCurrentSizeMappingIndex() {
|
||||
const mapping = this.mapping || [];
|
||||
let index = null;
|
||||
mapping.some((size, i) => {
|
||||
const [browserSize] = size;
|
||||
const [width, height] = browserSize;
|
||||
const mediaQuery = `(min-width: ${width}px) and (min-height: ${height}px)`;
|
||||
if (window.matchMedia(mediaQuery).matches) {
|
||||
index = i;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
return index;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (!window.googletag) {
|
||||
return;
|
||||
}
|
||||
const {
|
||||
ghostMode,
|
||||
adUnitPath,
|
||||
divId,
|
||||
sizeMapping,
|
||||
isResponsive,
|
||||
collapseEmptyDiv,
|
||||
} = this;
|
||||
|
||||
|
||||
// Init Ad slot
|
||||
googletag.cmd.push(() => {
|
||||
const pubadsService = googletag.pubads()
|
||||
pubadsService.addEventListener('slotRenderEnded', this.handleSlotRenderEnded);
|
||||
pubadsService.setTargeting('path', this.$route.path);
|
||||
|
||||
const adSlot = googletag
|
||||
.defineSlot(adUnitPath, this.formattedSize, divId)
|
||||
.addService(pubadsService);
|
||||
|
||||
// Collapse empty div slot-level override
|
||||
if (collapseEmptyDiv !== null) {
|
||||
adSlot.setCollapseEmptyDiv(collapseEmptyDiv);
|
||||
}
|
||||
|
||||
// Build size mapping if any
|
||||
if (sizeMapping.length > 0) {
|
||||
const mapping = googletag.sizeMapping();
|
||||
sizeMapping.forEach((size) => {
|
||||
const browserSize = this.formatSize(size[0]);
|
||||
const adSizes = this.formatSizeList(size[1]);
|
||||
mapping.addSize(browserSize, adSizes);
|
||||
this.mapping.push([browserSize, adSizes]);
|
||||
});
|
||||
adSlot.defineSizeMapping(mapping.build());
|
||||
}
|
||||
|
||||
// Init responsive behavior
|
||||
if (this.sizeMapping.length > 0 && isResponsive) {
|
||||
const currentSizeMappingIndex = this.getCurrentSizeMappingIndex();
|
||||
this.currentSizeMappingIndex = currentSizeMappingIndex;
|
||||
window.addEventListener('resize', this.handleWindowResize);
|
||||
}
|
||||
|
||||
this.adSlot = adSlot;
|
||||
this.$gptAds.slots.push(adSlot);
|
||||
|
||||
if (!this.ghostMode) {
|
||||
googletag.display(divId);
|
||||
if (this.$gptAds.individualRefresh) {
|
||||
this.refreshSlot();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (!googletag) {
|
||||
return;
|
||||
}
|
||||
// Destroy ad slot
|
||||
googletag.cmd.push(() => {
|
||||
const destroyed = googletag.destroySlots([this.adSlot]);
|
||||
});
|
||||
// Remove window resize listener
|
||||
window.removeEventListener('resize', this.handleWindowResize);
|
||||
},
|
||||
render(h) {
|
||||
const { divId, style, isEmpty } = this;
|
||||
let classAttr = isEmpty ? '<%= options.emptyClass %>' : '';
|
||||
|
||||
return h('div', {
|
||||
style,
|
||||
attrs: {
|
||||
id: divId,
|
||||
class: classAttr,
|
||||
},
|
||||
domProps: { innerHTML: '' },
|
||||
});
|
||||
},
|
||||
};
|
||||
111
modules/gpt-ads/lib/templates/plugin.js
Normal file
111
modules/gpt-ads/lib/templates/plugin.js
Normal file
@ -0,0 +1,111 @@
|
||||
import Vue from 'vue';
|
||||
|
||||
function isPersonalizedAdsOn(ctx) {
|
||||
let cookies = null
|
||||
if (ctx.req != null) {
|
||||
//Server side rendering
|
||||
cookies = ctx.req.headers.cookie;
|
||||
} else {
|
||||
// Rely on the client
|
||||
cookies = document.cookie;
|
||||
}
|
||||
let processed = {}
|
||||
cookies.split(';').forEach((e) => {
|
||||
let val = e.trim().split('=')
|
||||
processed[val[0]] = decodeURI(val[1])
|
||||
})
|
||||
let scopes = decodeURIComponent(processed['modrinth-scopes']).split(",")
|
||||
return (scopes !== null && scopes.includes('ads'))
|
||||
}
|
||||
|
||||
export default async function (ctx, inject) {
|
||||
|
||||
const { app } = ctx;
|
||||
const config = ctx.$config && ctx.$config.ads || {};
|
||||
// Module options
|
||||
const debug = config.debug ?? <%= options.debug || false %>;
|
||||
const individualRefresh = config.individualRefresh ?? <%= options.individualRefresh || false %>;
|
||||
const collapseEmptyDivs = config.collapseEmptyDivs ?? <%= options.collapseEmptyDivs || false %>;
|
||||
const GeoEdgeId = config.GeoEdgeId ?? '<%= options.geoEdgeId %>';
|
||||
const networkCode = config.networkCode ?? '<%= options.networkCode %>';
|
||||
const GPT_LIB_SCRIPT_ID = '<%= options.GPT_LIB_SCRIPT_ID %>';
|
||||
const GPT_INIT_SCRIPT_ID = '<%= options.GPT_INIT_SCRIPT_ID %>';
|
||||
const GEOEDGE_CONF_SCRIPT_ID = '<%= options.GEOEDGE_CONF_SCRIPT_ID %>';
|
||||
const GEOEDGE_LIB_SCRIPT_ID = '<%= options.GEOEDGE_LIB_SCRIPT_ID %>';
|
||||
// Instance options
|
||||
const gptAdsOptions = {
|
||||
networkCode,
|
||||
individualRefresh,
|
||||
slots: [],
|
||||
};
|
||||
|
||||
const injectScript = (script) => {
|
||||
const scriptIndex = ctx.app.head.script.findIndex(s => s.hid === script.hid);
|
||||
if (scriptIndex !== -1) {
|
||||
ctx.app.head.script[scriptIndex] = script;
|
||||
} else {
|
||||
ctx.app.head.script.push(script);
|
||||
}
|
||||
};
|
||||
let no_consent = !isPersonalizedAdsOn(ctx)
|
||||
|
||||
// GeoEdge support
|
||||
if (GeoEdgeId !== '') {
|
||||
// Unfortunately these lines are needed to prevent vue-meta from esacping quotes in the init script
|
||||
ctx.app.head.__dangerouslyDisableSanitizersByTagID = ctx.app.head.__dangerouslyDisableSanitizersByTagID || {}
|
||||
ctx.app.head.__dangerouslyDisableSanitizersByTagID[GEOEDGE_CONF_SCRIPT_ID] = ['innerHTML']
|
||||
const geoEdgeConfig = {
|
||||
hid: GEOEDGE_CONF_SCRIPT_ID,
|
||||
innerHTML: "window.grumi = { key: '" + encodeURIComponent(GeoEdgeId) +"'};"
|
||||
};
|
||||
injectScript(geoEdgeConfig);
|
||||
|
||||
const geoEdgeImport = {
|
||||
hid: GEOEDGE_LIB_SCRIPT_ID,
|
||||
src: `https://rumcdn.geoedge.be/${GeoEdgeId}/grumi-ip.js`,
|
||||
async: true,
|
||||
};
|
||||
injectScript(geoEdgeImport)
|
||||
}
|
||||
|
||||
// Inject GPT lib
|
||||
const gptLibScript = {
|
||||
hid: GPT_LIB_SCRIPT_ID,
|
||||
src: 'https://www.googletagservices.com/tag/js/gpt.js',
|
||||
async: true,
|
||||
};
|
||||
injectScript(gptLibScript);
|
||||
|
||||
// Inject GPT init script
|
||||
let gptInitScriptHtml = 'var googletag = googletag || {};googletag.cmd = googletag.cmd || [];';
|
||||
if (debug) {
|
||||
gptInitScriptHtml += 'googletag.cmd.push(function(){googletag.openConsole();});';
|
||||
}
|
||||
// Disable initial load
|
||||
const gptDisableInitialLoad = individualRefresh ? 'googletag.pubads().disableInitialLoad();' : '';
|
||||
// Collapse empty div
|
||||
const gptCollapseEmptyDivs = collapseEmptyDivs ? 'googletag.pubads().collapseEmptyDivs();' : '';
|
||||
// Desactivate personalization
|
||||
const gptDisablePersonalization = no_consent ? 'googletag.pubads().setRequestNonPersonalizedAds(1);' : '';
|
||||
gptInitScriptHtml += `
|
||||
googletag.cmd.push(function(){
|
||||
googletag.pubads().enableSingleRequest();
|
||||
${gptDisableInitialLoad}
|
||||
${gptCollapseEmptyDivs}
|
||||
${gptDisablePersonalization}
|
||||
googletag.enableServices();
|
||||
});
|
||||
`;
|
||||
const gptInitScript = {
|
||||
hid: GPT_INIT_SCRIPT_ID,
|
||||
innerHTML: gptInitScriptHtml,
|
||||
};
|
||||
injectScript(gptInitScript);
|
||||
|
||||
|
||||
const component = require('./component.js');
|
||||
Vue.component('<%= options.componentName %>', component.default || component);
|
||||
|
||||
inject('gptAds', gptAdsOptions);
|
||||
}
|
||||
|
||||
35
modules/gpt-ads/package.json
Normal file
35
modules/gpt-ads/package.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "@ax2/gpt-ads-module",
|
||||
"version": "0.6.0",
|
||||
"description": "Google Publisher Tag ads integration for Nuxt",
|
||||
"license": "MIT",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Paul Gascou-Vaillancourt <paul@ax2.ca>"
|
||||
}
|
||||
],
|
||||
"main": "lib/module.js",
|
||||
"repository": "https://github.com/ax2inc/nuxt-modules",
|
||||
"homepage": "https://github.com/ax2inc/nuxt-modules/tree/master/packages/gpt-ads#readme",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"devDependencies": {
|
||||
"codecov": "latest",
|
||||
"eslint": "5.13.0",
|
||||
"eslint-config-airbnb-base": "13.1.0",
|
||||
"eslint-loader": "2.1.2",
|
||||
"eslint-plugin-import": "2.16.0",
|
||||
"eslint-plugin-jest": "22.3.0",
|
||||
"eslint-plugin-vue": "5.2.1",
|
||||
"jest": "24.1.0",
|
||||
"jsdom": "14.0.0",
|
||||
"nuxt": "2.4.3",
|
||||
"request-promise-native": "1.0.5",
|
||||
"standard-version": "latest"
|
||||
},
|
||||
"gitHead": "db930bf38f5eec5696ad7978a68656436831fc59"
|
||||
}
|
||||
@ -61,14 +61,7 @@ export default {
|
||||
'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700;800&display=swap',
|
||||
},
|
||||
],
|
||||
script: [
|
||||
{
|
||||
src: 'https://analytics.modrinth.com/umami.js',
|
||||
'data-website-id': 'c37613de-245d-4767-90e7-ba7980a4f1a2',
|
||||
async: true,
|
||||
defer: true,
|
||||
},
|
||||
],
|
||||
script: [],
|
||||
},
|
||||
|
||||
vue: {
|
||||
@ -78,7 +71,7 @@ export default {
|
||||
},
|
||||
},
|
||||
router: {
|
||||
middleware: 'auth',
|
||||
middleware: ['auth', 'ads_tracking'],
|
||||
},
|
||||
/*
|
||||
** Global CSS
|
||||
@ -119,9 +112,20 @@ export default {
|
||||
'@nuxtjs/robots',
|
||||
'@nuxtjs/sitemap',
|
||||
'@nuxtjs/style-resources',
|
||||
'@nuxtjs/google-adsense',
|
||||
'cookie-universal-nuxt',
|
||||
'~/modules/gpt-ads',
|
||||
'~/modules/analytics',
|
||||
],
|
||||
ads: {
|
||||
// Module options
|
||||
ghostMode: true,
|
||||
geoEdgeId: '',
|
||||
},
|
||||
analytics: {
|
||||
enabled: false,
|
||||
script_url: '',
|
||||
tracking_code: '',
|
||||
},
|
||||
robots: {
|
||||
Sitemap: 'https://modrinth.com/sitemap.xml',
|
||||
},
|
||||
@ -139,9 +143,6 @@ export default {
|
||||
},
|
||||
},
|
||||
},
|
||||
'google-adsense': {
|
||||
id: 'ca-pub-4615302805870170',
|
||||
},
|
||||
dayjs: {
|
||||
locales: ['en'],
|
||||
defaultLocale: 'en',
|
||||
@ -170,4 +171,16 @@ export default {
|
||||
env: {
|
||||
version: process.env.VERSION_ID || 'unknown',
|
||||
},
|
||||
publicRuntimeConfig: {
|
||||
ads: {
|
||||
ghostMode: process.env.ENABLE_ADS == null,
|
||||
GeoEdgeId: process.env.GEOEDGE_ID,
|
||||
networkCode: process.env.GAM_ID,
|
||||
},
|
||||
analytics: {
|
||||
enabled: process.env.ENABLE_ANALYTICS,
|
||||
script_url: process.env.ANALYTICS_URL,
|
||||
tracking_code: process.env.ANALYTICS_ID,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
671
package-lock.json
generated
671
package-lock.json
generated
@ -5,7 +5,6 @@
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "knossos",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@nuxtjs/axios": "^5.12.5",
|
||||
@ -26,6 +25,7 @@
|
||||
"xss": "^1.0.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nuxt/types": "^2.14.12",
|
||||
"@nuxtjs/color-mode": "^1.1.1",
|
||||
"@nuxtjs/eslint-config": "^3.1.0",
|
||||
"@nuxtjs/eslint-module": "^2.0.0",
|
||||
@ -2106,6 +2106,61 @@
|
||||
"resolved": "https://registry.npmjs.org/defu/-/defu-2.0.4.tgz",
|
||||
"integrity": "sha512-G9pEH1UUMxShy6syWk01VQSRVs3CDWtlxtZu7A+NyqjxaCA4gSlWAKDBx6QiUEKezqS8+DUlXLI14Fp05Hmpwg=="
|
||||
},
|
||||
"node_modules/@nuxt/types": {
|
||||
"version": "2.14.12",
|
||||
"resolved": "https://registry.npmjs.org/@nuxt/types/-/types-2.14.12.tgz",
|
||||
"integrity": "sha512-x58uEVygHual/kHDTrLAwXjKNYn+5udR4HJOmHd2gXgYonZu8E2UpsShIkyMRZ0nRoEAZ72i4OfcHKqGsVSI6w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/autoprefixer": "^9.7.2",
|
||||
"@types/babel__core": "^7.1.12",
|
||||
"@types/compression": "^1.7.0",
|
||||
"@types/connect": "^3.4.33",
|
||||
"@types/etag": "^1.8.0",
|
||||
"@types/file-loader": "^4.2.0",
|
||||
"@types/html-minifier": "^4.0.0",
|
||||
"@types/less": "^3.0.1",
|
||||
"@types/node": "^12.19.8",
|
||||
"@types/node-sass": "^4.11.1",
|
||||
"@types/optimize-css-assets-webpack-plugin": "^5.0.1",
|
||||
"@types/pug": "^2.0.4",
|
||||
"@types/serve-static": "^1.13.8",
|
||||
"@types/terser-webpack-plugin": "^2.2.0",
|
||||
"@types/webpack": "^4.41.25",
|
||||
"@types/webpack-bundle-analyzer": "^3.9.0",
|
||||
"@types/webpack-dev-middleware": "^3.7.2",
|
||||
"@types/webpack-hot-middleware": "^2.25.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/types/node_modules/@types/node": {
|
||||
"version": "12.20.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.7.tgz",
|
||||
"integrity": "sha512-gWL8VUkg8VRaCAUgG9WmhefMqHmMblxe2rVpMF86nZY/+ZysU+BkAp+3cz03AixWDSSz0ks5WX59yAhv/cDwFA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@nuxt/types/node_modules/@types/webpack": {
|
||||
"version": "4.41.27",
|
||||
"resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.27.tgz",
|
||||
"integrity": "sha512-wK/oi5gcHi72VMTbOaQ70VcDxSQ1uX8S2tukBK9ARuGXrYM/+u4ou73roc7trXDNmCxCoerE8zruQqX/wuHszA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/anymatch": "*",
|
||||
"@types/node": "*",
|
||||
"@types/tapable": "^1",
|
||||
"@types/uglify-js": "*",
|
||||
"@types/webpack-sources": "*",
|
||||
"source-map": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/types/node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nuxt/utils": {
|
||||
"version": "2.14.7",
|
||||
"resolved": "https://registry.npmjs.org/@nuxt/utils/-/utils-2.14.7.tgz",
|
||||
@ -2504,11 +2559,170 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz",
|
||||
"integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA=="
|
||||
},
|
||||
"node_modules/@types/autoprefixer": {
|
||||
"version": "9.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/autoprefixer/-/autoprefixer-9.7.2.tgz",
|
||||
"integrity": "sha512-QX7U7YW3zX3ex6MECtWO9folTGsXeP4b8bSjTq3I1ODM+H+sFHwGKuof+T+qBcDClGlCGtDb3SVfiTVfmcxw4g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/browserslist": "*",
|
||||
"postcss": "7.x.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/babel__core": {
|
||||
"version": "7.1.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.14.tgz",
|
||||
"integrity": "sha512-zGZJzzBUVDo/eV6KgbE0f0ZI7dInEYvo12Rb70uNQDshC3SkRMb67ja0GgRHZgAX3Za6rhaWlvbDO8rrGyAb1g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.1.0",
|
||||
"@babel/types": "^7.0.0",
|
||||
"@types/babel__generator": "*",
|
||||
"@types/babel__template": "*",
|
||||
"@types/babel__traverse": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/babel__generator": {
|
||||
"version": "7.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.2.tgz",
|
||||
"integrity": "sha512-MdSJnBjl+bdwkLskZ3NGFp9YcXGx5ggLpQQPqtgakVhsWK0hTtNYhjpZLlWQTviGTvF8at+Bvli3jV7faPdgeQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/babel__template": {
|
||||
"version": "7.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.0.tgz",
|
||||
"integrity": "sha512-NTPErx4/FiPCGScH7foPyr+/1Dkzkni+rHiYHHoTjvwou7AQzJkNeD60A9CXRy+ZEN2B1bggmkTMCDb+Mv5k+A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.1.0",
|
||||
"@babel/types": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/babel__traverse": {
|
||||
"version": "7.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.11.1.tgz",
|
||||
"integrity": "sha512-Vs0hm0vPahPMYi9tDjtP66llufgO3ST16WXaSTtDGEl9cewAl3AibmxWw6TINOqHPT9z0uABKAYjT9jNSg4npw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/body-parser": {
|
||||
"version": "1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz",
|
||||
"integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/connect": "*",
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/browserslist": {
|
||||
"version": "4.15.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/browserslist/-/browserslist-4.15.0.tgz",
|
||||
"integrity": "sha512-h9LyKErRGZqMsHh9bd+FE8yCIal4S0DxKTOeui56VgVXqa66TKiuaIUxCAI7c1O0LjaUzOTcsMyOpO9GetozRA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"browserslist": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/clean-css": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/clean-css/-/clean-css-4.2.3.tgz",
|
||||
"integrity": "sha512-ET0ldU/vpXecy5vO8JRIhtJWSrk1vzXdJcp3Bjf8bARZynl6vfkhEKY/A7njfNIRlmyTGuVFuqnD6I3tOGdXpQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"source-map": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/clean-css/node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/compression": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.7.0.tgz",
|
||||
"integrity": "sha512-3LzWUM+3k3XdWOUk/RO+uSjv7YWOatYq2QADJntK1pjkk4DfVP0KrIEPDnXRJxAAGKe0VpIPRmlINLDuCedZWw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/express": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/connect": {
|
||||
"version": "3.4.34",
|
||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz",
|
||||
"integrity": "sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/cookie": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz",
|
||||
"integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow=="
|
||||
},
|
||||
"node_modules/@types/etag": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/etag/-/etag-1.8.0.tgz",
|
||||
"integrity": "sha512-EdSN0x+Y0/lBv7YAb8IU4Jgm6DWM+Bqtz7o5qozl96fzaqdqbdfHS5qjdpFeIv7xQ8jSLyjMMNShgYtMajEHyQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/express": {
|
||||
"version": "4.17.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.11.tgz",
|
||||
"integrity": "sha512-no+R6rW60JEc59977wIxreQVsIEOAYwgCqldrA/vkpCnbD7MqTefO97lmoBe4WE0F156bC4uLSP1XHDOySnChg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/body-parser": "*",
|
||||
"@types/express-serve-static-core": "^4.17.18",
|
||||
"@types/qs": "*",
|
||||
"@types/serve-static": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/express-serve-static-core": {
|
||||
"version": "4.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.19.tgz",
|
||||
"integrity": "sha512-DJOSHzX7pCiSElWaGR8kCprwibCB/3yW6vcT8VG3P0SJjnv19gnWG/AZMfM60Xj/YJIp/YCaDHyvzsFVeniARA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"@types/qs": "*",
|
||||
"@types/range-parser": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/file-loader": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/file-loader/-/file-loader-4.2.1.tgz",
|
||||
"integrity": "sha512-ImtIwnIEEMgyE7DK1JduhiDv+8WzfRWb3BPuf6RiBD1ySz05vyDRhGiKvIcuUPxUzMNBRZHN0pB+bWXSX3+t1w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/webpack": "^4"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/html-minifier": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/html-minifier/-/html-minifier-4.0.0.tgz",
|
||||
"integrity": "sha512-eFnGhrKmjWBlnSGNtunetE3UU2Tc/LUl92htFslSSTmpp9EKHQVcYQadCyYfnzUEFB5G/3wLWo/USQS/mEPKrA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/clean-css": "*",
|
||||
"@types/relateurl": "*",
|
||||
"@types/uglify-js": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/html-minifier-terser": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz",
|
||||
@ -2533,22 +2747,85 @@
|
||||
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/less": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/less/-/less-3.0.2.tgz",
|
||||
"integrity": "sha512-62vfe65cMSzYaWmpmhqCMMNl0khen89w57mByPi1OseGfcV/LV03fO8YVrNj7rFQsRWNJo650WWyh6m7p8vZmA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/memory-fs": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/memory-fs/-/memory-fs-0.3.3.tgz",
|
||||
"integrity": "sha512-rLEYzl1xODshz+Lm+YX8NYws8Xw7/qcYbQInMkotl96VpLZmUvoCfYYGxfajMSiugANV02QO5Fc+R98KKeE4gQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/mime": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
|
||||
"integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "14.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.2.tgz",
|
||||
"integrity": "sha512-onlIwbaeqvZyniGPfdw/TEhKIh79pz66L1q06WUQqJLnAb6wbjvOtepLYTGHTqzdXgBYIE3ZdmqHDGsRsbBz7A=="
|
||||
},
|
||||
"node_modules/@types/node-sass": {
|
||||
"version": "4.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node-sass/-/node-sass-4.11.1.tgz",
|
||||
"integrity": "sha512-wPOmOEEtbwQiPTIgzUuRSQZ3H5YHinsxRGeZzPSDefAm4ylXWnZG9C0adses8ymyplKK0gwv3JkDNO8GGxnWfg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/normalize-package-data": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
|
||||
"integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/optimize-css-assets-webpack-plugin": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.3.tgz",
|
||||
"integrity": "sha512-PJgbI4KplJfyxKWVrBbEL+rePEBqeozJRMT0mBL3ynhvngASBV/XJ+BneLuJN74RjjMzO0gA5ns80mgubQdZAA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/webpack": "^4"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/pug": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.4.tgz",
|
||||
"integrity": "sha1-h3L80EGOPNLMFxVV1zAHQVBR9LI=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/q": {
|
||||
"version": "1.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz",
|
||||
"integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug=="
|
||||
},
|
||||
"node_modules/@types/qs": {
|
||||
"version": "6.9.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.6.tgz",
|
||||
"integrity": "sha512-0/HnwIfW4ki2D8L8c9GVcG5I72s9jP5GSLVF0VIXDW00kmIpA6O33G7a8n59Tmh7Nz0WUC3rSb7PTY/sdW2JzA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/range-parser": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
|
||||
"integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/relateurl": {
|
||||
"version": "0.2.28",
|
||||
"resolved": "https://registry.npmjs.org/@types/relateurl/-/relateurl-0.2.28.tgz",
|
||||
"integrity": "sha1-a9p9uGU/piZD9e5p6facEaOS46Y=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/sax": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.1.tgz",
|
||||
@ -2557,6 +2834,16 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/serve-static": {
|
||||
"version": "1.13.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.9.tgz",
|
||||
"integrity": "sha512-ZFqF6qa48XsPdjXV5Gsz0Zqmux2PerNd3a/ktL45mHpa19cuMi/cL8tcxdAx497yRh+QtYPuofjT9oWw9P7nkA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/mime": "^1",
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/source-list-map": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz",
|
||||
@ -2567,6 +2854,16 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.6.tgz",
|
||||
"integrity": "sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA=="
|
||||
},
|
||||
"node_modules/@types/terser-webpack-plugin": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/terser-webpack-plugin/-/terser-webpack-plugin-2.2.2.tgz",
|
||||
"integrity": "sha512-cesfeuYsaBJwGVvhJC0b8bgKnsxeNT1MkEpy1BhLrEgi1U1SATenWew2J8vr9aZLRcpf6D3T+ReVtoq0vGswuQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/webpack": "^4",
|
||||
"terser": "^4.3.9"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/uglify-js": {
|
||||
"version": "3.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.11.0.tgz",
|
||||
@ -2596,6 +2893,37 @@
|
||||
"source-map": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/webpack-bundle-analyzer": {
|
||||
"version": "3.9.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.9.2.tgz",
|
||||
"integrity": "sha512-+LirhEpWEPRMyOW0HCy/lTTGzfdEWL26ximknO+/oaAQkigJJktxMr/QE7EWVNMRv+hpwW20Mv3YfLs42q2kjA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/webpack": "^4"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/webpack-dev-middleware": {
|
||||
"version": "3.7.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/webpack-dev-middleware/-/webpack-dev-middleware-3.7.4.tgz",
|
||||
"integrity": "sha512-NV7qwBHYYOxgUo3PB12bBngpW7I4JY2AZTVLszmeNkmGH8DCgBTXKyc9t9KLaaATE07A9bXeJmyHFaE5OiV6mA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/connect": "*",
|
||||
"@types/memory-fs": "*",
|
||||
"@types/webpack": "^4",
|
||||
"loglevel": "^1.6.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/webpack-hot-middleware": {
|
||||
"version": "2.25.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/webpack-hot-middleware/-/webpack-hot-middleware-2.25.4.tgz",
|
||||
"integrity": "sha512-6tQb9EBKIANZYUVLQYWiWfDFVe7FhXSj4bB2EF5QB7VtYWL3HDR+y/zqjZPAnCorv0spLqVMRqjRK8AmhfocMw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/connect": "*",
|
||||
"@types/webpack": "^4"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/webpack-sources": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.0.0.tgz",
|
||||
@ -9375,6 +9703,15 @@
|
||||
"integrity": "sha1-7GZi5IlkCO1KtsVCo5kLcswIACA=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/loglevel": {
|
||||
"version": "1.7.1",
|
||||
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz",
|
||||
"integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/loud-rejection": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
|
||||
@ -18446,6 +18783,60 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@nuxt/types": {
|
||||
"version": "2.14.12",
|
||||
"resolved": "https://registry.npmjs.org/@nuxt/types/-/types-2.14.12.tgz",
|
||||
"integrity": "sha512-x58uEVygHual/kHDTrLAwXjKNYn+5udR4HJOmHd2gXgYonZu8E2UpsShIkyMRZ0nRoEAZ72i4OfcHKqGsVSI6w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/autoprefixer": "^9.7.2",
|
||||
"@types/babel__core": "^7.1.12",
|
||||
"@types/compression": "^1.7.0",
|
||||
"@types/connect": "^3.4.33",
|
||||
"@types/etag": "^1.8.0",
|
||||
"@types/file-loader": "^4.2.0",
|
||||
"@types/html-minifier": "^4.0.0",
|
||||
"@types/less": "^3.0.1",
|
||||
"@types/node": "^12.19.8",
|
||||
"@types/node-sass": "^4.11.1",
|
||||
"@types/optimize-css-assets-webpack-plugin": "^5.0.1",
|
||||
"@types/pug": "^2.0.4",
|
||||
"@types/serve-static": "^1.13.8",
|
||||
"@types/terser-webpack-plugin": "^2.2.0",
|
||||
"@types/webpack": "^4.41.25",
|
||||
"@types/webpack-bundle-analyzer": "^3.9.0",
|
||||
"@types/webpack-dev-middleware": "^3.7.2",
|
||||
"@types/webpack-hot-middleware": "^2.25.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "12.20.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.7.tgz",
|
||||
"integrity": "sha512-gWL8VUkg8VRaCAUgG9WmhefMqHmMblxe2rVpMF86nZY/+ZysU+BkAp+3cz03AixWDSSz0ks5WX59yAhv/cDwFA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/webpack": {
|
||||
"version": "4.41.27",
|
||||
"resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.27.tgz",
|
||||
"integrity": "sha512-wK/oi5gcHi72VMTbOaQ70VcDxSQ1uX8S2tukBK9ARuGXrYM/+u4ou73roc7trXDNmCxCoerE8zruQqX/wuHszA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/anymatch": "*",
|
||||
"@types/node": "*",
|
||||
"@types/tapable": "^1",
|
||||
"@types/uglify-js": "*",
|
||||
"@types/webpack-sources": "*",
|
||||
"source-map": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@nuxt/utils": {
|
||||
"version": "2.14.7",
|
||||
"resolved": "https://registry.npmjs.org/@nuxt/utils/-/utils-2.14.7.tgz",
|
||||
@ -18810,11 +19201,169 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz",
|
||||
"integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA=="
|
||||
},
|
||||
"@types/autoprefixer": {
|
||||
"version": "9.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/autoprefixer/-/autoprefixer-9.7.2.tgz",
|
||||
"integrity": "sha512-QX7U7YW3zX3ex6MECtWO9folTGsXeP4b8bSjTq3I1ODM+H+sFHwGKuof+T+qBcDClGlCGtDb3SVfiTVfmcxw4g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/browserslist": "*",
|
||||
"postcss": "7.x.x"
|
||||
}
|
||||
},
|
||||
"@types/babel__core": {
|
||||
"version": "7.1.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.14.tgz",
|
||||
"integrity": "sha512-zGZJzzBUVDo/eV6KgbE0f0ZI7dInEYvo12Rb70uNQDshC3SkRMb67ja0GgRHZgAX3Za6rhaWlvbDO8rrGyAb1g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/parser": "^7.1.0",
|
||||
"@babel/types": "^7.0.0",
|
||||
"@types/babel__generator": "*",
|
||||
"@types/babel__template": "*",
|
||||
"@types/babel__traverse": "*"
|
||||
}
|
||||
},
|
||||
"@types/babel__generator": {
|
||||
"version": "7.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.2.tgz",
|
||||
"integrity": "sha512-MdSJnBjl+bdwkLskZ3NGFp9YcXGx5ggLpQQPqtgakVhsWK0hTtNYhjpZLlWQTviGTvF8at+Bvli3jV7faPdgeQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/types": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@types/babel__template": {
|
||||
"version": "7.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.0.tgz",
|
||||
"integrity": "sha512-NTPErx4/FiPCGScH7foPyr+/1Dkzkni+rHiYHHoTjvwou7AQzJkNeD60A9CXRy+ZEN2B1bggmkTMCDb+Mv5k+A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/parser": "^7.1.0",
|
||||
"@babel/types": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@types/babel__traverse": {
|
||||
"version": "7.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.11.1.tgz",
|
||||
"integrity": "sha512-Vs0hm0vPahPMYi9tDjtP66llufgO3ST16WXaSTtDGEl9cewAl3AibmxWw6TINOqHPT9z0uABKAYjT9jNSg4npw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/types": "^7.3.0"
|
||||
}
|
||||
},
|
||||
"@types/body-parser": {
|
||||
"version": "1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz",
|
||||
"integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/connect": "*",
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/browserslist": {
|
||||
"version": "4.15.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/browserslist/-/browserslist-4.15.0.tgz",
|
||||
"integrity": "sha512-h9LyKErRGZqMsHh9bd+FE8yCIal4S0DxKTOeui56VgVXqa66TKiuaIUxCAI7c1O0LjaUzOTcsMyOpO9GetozRA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"browserslist": "*"
|
||||
}
|
||||
},
|
||||
"@types/clean-css": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/clean-css/-/clean-css-4.2.3.tgz",
|
||||
"integrity": "sha512-ET0ldU/vpXecy5vO8JRIhtJWSrk1vzXdJcp3Bjf8bARZynl6vfkhEKY/A7njfNIRlmyTGuVFuqnD6I3tOGdXpQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*",
|
||||
"source-map": "^0.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/compression": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.7.0.tgz",
|
||||
"integrity": "sha512-3LzWUM+3k3XdWOUk/RO+uSjv7YWOatYq2QADJntK1pjkk4DfVP0KrIEPDnXRJxAAGKe0VpIPRmlINLDuCedZWw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/express": "*"
|
||||
}
|
||||
},
|
||||
"@types/connect": {
|
||||
"version": "3.4.34",
|
||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz",
|
||||
"integrity": "sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/cookie": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz",
|
||||
"integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow=="
|
||||
},
|
||||
"@types/etag": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/etag/-/etag-1.8.0.tgz",
|
||||
"integrity": "sha512-EdSN0x+Y0/lBv7YAb8IU4Jgm6DWM+Bqtz7o5qozl96fzaqdqbdfHS5qjdpFeIv7xQ8jSLyjMMNShgYtMajEHyQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/express": {
|
||||
"version": "4.17.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.11.tgz",
|
||||
"integrity": "sha512-no+R6rW60JEc59977wIxreQVsIEOAYwgCqldrA/vkpCnbD7MqTefO97lmoBe4WE0F156bC4uLSP1XHDOySnChg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/body-parser": "*",
|
||||
"@types/express-serve-static-core": "^4.17.18",
|
||||
"@types/qs": "*",
|
||||
"@types/serve-static": "*"
|
||||
}
|
||||
},
|
||||
"@types/express-serve-static-core": {
|
||||
"version": "4.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.19.tgz",
|
||||
"integrity": "sha512-DJOSHzX7pCiSElWaGR8kCprwibCB/3yW6vcT8VG3P0SJjnv19gnWG/AZMfM60Xj/YJIp/YCaDHyvzsFVeniARA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*",
|
||||
"@types/qs": "*",
|
||||
"@types/range-parser": "*"
|
||||
}
|
||||
},
|
||||
"@types/file-loader": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/file-loader/-/file-loader-4.2.1.tgz",
|
||||
"integrity": "sha512-ImtIwnIEEMgyE7DK1JduhiDv+8WzfRWb3BPuf6RiBD1ySz05vyDRhGiKvIcuUPxUzMNBRZHN0pB+bWXSX3+t1w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/webpack": "^4"
|
||||
}
|
||||
},
|
||||
"@types/html-minifier": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/html-minifier/-/html-minifier-4.0.0.tgz",
|
||||
"integrity": "sha512-eFnGhrKmjWBlnSGNtunetE3UU2Tc/LUl92htFslSSTmpp9EKHQVcYQadCyYfnzUEFB5G/3wLWo/USQS/mEPKrA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/clean-css": "*",
|
||||
"@types/relateurl": "*",
|
||||
"@types/uglify-js": "*"
|
||||
}
|
||||
},
|
||||
"@types/html-minifier-terser": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz",
|
||||
@ -18839,22 +19388,85 @@
|
||||
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
|
||||
"dev": true
|
||||
},
|
||||
"@types/less": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/less/-/less-3.0.2.tgz",
|
||||
"integrity": "sha512-62vfe65cMSzYaWmpmhqCMMNl0khen89w57mByPi1OseGfcV/LV03fO8YVrNj7rFQsRWNJo650WWyh6m7p8vZmA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/memory-fs": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/memory-fs/-/memory-fs-0.3.3.tgz",
|
||||
"integrity": "sha512-rLEYzl1xODshz+Lm+YX8NYws8Xw7/qcYbQInMkotl96VpLZmUvoCfYYGxfajMSiugANV02QO5Fc+R98KKeE4gQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/mime": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
|
||||
"integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "14.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.2.tgz",
|
||||
"integrity": "sha512-onlIwbaeqvZyniGPfdw/TEhKIh79pz66L1q06WUQqJLnAb6wbjvOtepLYTGHTqzdXgBYIE3ZdmqHDGsRsbBz7A=="
|
||||
},
|
||||
"@types/node-sass": {
|
||||
"version": "4.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node-sass/-/node-sass-4.11.1.tgz",
|
||||
"integrity": "sha512-wPOmOEEtbwQiPTIgzUuRSQZ3H5YHinsxRGeZzPSDefAm4ylXWnZG9C0adses8ymyplKK0gwv3JkDNO8GGxnWfg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/normalize-package-data": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
|
||||
"integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/optimize-css-assets-webpack-plugin": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.3.tgz",
|
||||
"integrity": "sha512-PJgbI4KplJfyxKWVrBbEL+rePEBqeozJRMT0mBL3ynhvngASBV/XJ+BneLuJN74RjjMzO0gA5ns80mgubQdZAA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/webpack": "^4"
|
||||
}
|
||||
},
|
||||
"@types/pug": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.4.tgz",
|
||||
"integrity": "sha1-h3L80EGOPNLMFxVV1zAHQVBR9LI=",
|
||||
"dev": true
|
||||
},
|
||||
"@types/q": {
|
||||
"version": "1.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz",
|
||||
"integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug=="
|
||||
},
|
||||
"@types/qs": {
|
||||
"version": "6.9.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.6.tgz",
|
||||
"integrity": "sha512-0/HnwIfW4ki2D8L8c9GVcG5I72s9jP5GSLVF0VIXDW00kmIpA6O33G7a8n59Tmh7Nz0WUC3rSb7PTY/sdW2JzA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/range-parser": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
|
||||
"integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/relateurl": {
|
||||
"version": "0.2.28",
|
||||
"resolved": "https://registry.npmjs.org/@types/relateurl/-/relateurl-0.2.28.tgz",
|
||||
"integrity": "sha1-a9p9uGU/piZD9e5p6facEaOS46Y=",
|
||||
"dev": true
|
||||
},
|
||||
"@types/sax": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.1.tgz",
|
||||
@ -18863,6 +19475,16 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/serve-static": {
|
||||
"version": "1.13.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.9.tgz",
|
||||
"integrity": "sha512-ZFqF6qa48XsPdjXV5Gsz0Zqmux2PerNd3a/ktL45mHpa19cuMi/cL8tcxdAx497yRh+QtYPuofjT9oWw9P7nkA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/mime": "^1",
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/source-list-map": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz",
|
||||
@ -18873,6 +19495,16 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.6.tgz",
|
||||
"integrity": "sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA=="
|
||||
},
|
||||
"@types/terser-webpack-plugin": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/terser-webpack-plugin/-/terser-webpack-plugin-2.2.2.tgz",
|
||||
"integrity": "sha512-cesfeuYsaBJwGVvhJC0b8bgKnsxeNT1MkEpy1BhLrEgi1U1SATenWew2J8vr9aZLRcpf6D3T+ReVtoq0vGswuQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/webpack": "^4",
|
||||
"terser": "^4.3.9"
|
||||
}
|
||||
},
|
||||
"@types/uglify-js": {
|
||||
"version": "3.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.11.0.tgz",
|
||||
@ -18908,6 +19540,37 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/webpack-bundle-analyzer": {
|
||||
"version": "3.9.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.9.2.tgz",
|
||||
"integrity": "sha512-+LirhEpWEPRMyOW0HCy/lTTGzfdEWL26ximknO+/oaAQkigJJktxMr/QE7EWVNMRv+hpwW20Mv3YfLs42q2kjA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/webpack": "^4"
|
||||
}
|
||||
},
|
||||
"@types/webpack-dev-middleware": {
|
||||
"version": "3.7.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/webpack-dev-middleware/-/webpack-dev-middleware-3.7.4.tgz",
|
||||
"integrity": "sha512-NV7qwBHYYOxgUo3PB12bBngpW7I4JY2AZTVLszmeNkmGH8DCgBTXKyc9t9KLaaATE07A9bXeJmyHFaE5OiV6mA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/connect": "*",
|
||||
"@types/memory-fs": "*",
|
||||
"@types/webpack": "^4",
|
||||
"loglevel": "^1.6.2"
|
||||
}
|
||||
},
|
||||
"@types/webpack-hot-middleware": {
|
||||
"version": "2.25.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/webpack-hot-middleware/-/webpack-hot-middleware-2.25.4.tgz",
|
||||
"integrity": "sha512-6tQb9EBKIANZYUVLQYWiWfDFVe7FhXSj4bB2EF5QB7VtYWL3HDR+y/zqjZPAnCorv0spLqVMRqjRK8AmhfocMw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/connect": "*",
|
||||
"@types/webpack": "^4"
|
||||
}
|
||||
},
|
||||
"@types/webpack-sources": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.0.0.tgz",
|
||||
@ -24555,6 +25218,12 @@
|
||||
"integrity": "sha1-7GZi5IlkCO1KtsVCo5kLcswIACA=",
|
||||
"dev": true
|
||||
},
|
||||
"loglevel": {
|
||||
"version": "1.7.1",
|
||||
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz",
|
||||
"integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==",
|
||||
"dev": true
|
||||
},
|
||||
"loud-rejection": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
"start": "nuxt start",
|
||||
"export": "nuxt export",
|
||||
"serve": "nuxt serve",
|
||||
"lint:js": "eslint --ext .js,.vue --ignore-path .gitignore .",
|
||||
"lint:js": "eslint --ext .js,.vue --ignore-path .eslintignore .",
|
||||
"lint": "npm run lint:js"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -30,6 +30,7 @@
|
||||
"xss": "^1.0.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nuxt/types": "^2.14.12",
|
||||
"@nuxtjs/color-mode": "^1.1.1",
|
||||
"@nuxtjs/eslint-config": "^3.1.0",
|
||||
"@nuxtjs/eslint-module": "^2.0.0",
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="page-container">
|
||||
<div class="page-contents">
|
||||
<div class="sidebar-l">
|
||||
<div class="card page-nav">
|
||||
<div v-if="$auth.user != null" class="card page-nav">
|
||||
<nuxt-link :to="'/dashboard/projects'" class="tab last">
|
||||
<ModIcon />
|
||||
My mods
|
||||
@ -30,6 +30,16 @@
|
||||
Settings
|
||||
</nuxt-link>
|
||||
</div>
|
||||
<div v-else class="card page-nav">
|
||||
<a :href="authUrl" class="tab last">
|
||||
<UserIcon />
|
||||
Log in
|
||||
</a>
|
||||
<nuxt-link :to="'/dashboard/privacy'" class="tab last">
|
||||
<SettingsIcon />
|
||||
Privacy Settings
|
||||
</nuxt-link>
|
||||
</div>
|
||||
<m-footer class="footer" />
|
||||
</div>
|
||||
<div class="content">
|
||||
@ -44,6 +54,7 @@ import ModerationIcon from '~/assets/images/sidebar/admin.svg?inline'
|
||||
import SettingsIcon from '~/assets/images/sidebar/settings.svg?inline'
|
||||
import NotificationsIcon from '~/assets/images/sidebar/notifications.svg?inline'
|
||||
import FollowIcon from '~/assets/images/utils/heart.svg?inline'
|
||||
import UserIcon from '~/assets/images/utils/user.svg?inline'
|
||||
|
||||
export default {
|
||||
name: 'DashboardPage',
|
||||
@ -53,6 +64,12 @@ export default {
|
||||
SettingsIcon,
|
||||
NotificationsIcon,
|
||||
FollowIcon,
|
||||
UserIcon,
|
||||
},
|
||||
computed: {
|
||||
authUrl() {
|
||||
return `https://api.modrinth.com/api/v1/auth/init?url=https://modrinth.com${this.$route.fullPath}`
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
161
pages/dashboard/privacy.vue
Normal file
161
pages/dashboard/privacy.vue
Normal file
@ -0,0 +1,161 @@
|
||||
<!--suppress HtmlFormInputWithoutLabel -->
|
||||
<template>
|
||||
<div class="popup card">
|
||||
<div class="consent-container">
|
||||
<div class="h1">Tweak your privacy settings</div>
|
||||
<div>
|
||||
Modrinth relies on different providers and in-house tools to allow us to
|
||||
provide custom-tailored experiences, and personalized advertising. You
|
||||
can at any moment change your privacy settings by going to the setting
|
||||
page, or at the footer of any page.
|
||||
</div>
|
||||
<br class="divider" />
|
||||
<div class="toggles">
|
||||
<div v-for="(scope, id) in scopes" :key="id" class="toggle">
|
||||
<div class="toggle-text">
|
||||
<div class="title">{{ scope.title }}</div>
|
||||
<div class="contents">
|
||||
{{ scope.description }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="spacer"></div>
|
||||
<div class="toggle-action">
|
||||
<label :for="id"></label>
|
||||
<input
|
||||
:id="id"
|
||||
ref="toggles"
|
||||
v-model="scopes[id].value"
|
||||
type="checkbox"
|
||||
class="switch stylized-toggle"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button class="btn button" @click="toggleOff">Refuse All</button>
|
||||
<button class="btn button" @click="toggleOn">Accept All</button>
|
||||
<button class="btn brand-button" @click="confirm">
|
||||
Confirm my choices
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/* eslint-disable require-await */
|
||||
import scopes from '@/privacy-toggles'
|
||||
export default {
|
||||
name: 'Privacy',
|
||||
data: () => {
|
||||
const settings = scopes.settings
|
||||
return {
|
||||
scopes: settings,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$store.dispatch('consent/loadFromCookies', this.$cookies)
|
||||
// Load the allowed scopes from the store
|
||||
this.$store.state.consent.scopes_allowed.forEach((scope) => {
|
||||
if (this.scopes[scope] != null)
|
||||
this.$set(this.scopes[scope], 'value', true)
|
||||
})
|
||||
},
|
||||
options: {
|
||||
auth: false,
|
||||
},
|
||||
methods: {
|
||||
toggleOff() {
|
||||
for (const elem in this.scopes) {
|
||||
this.$set(this.scopes[elem], 'value', false)
|
||||
}
|
||||
},
|
||||
toggleOn() {
|
||||
for (const elem in this.scopes) {
|
||||
this.$set(this.scopes[elem], 'value', true)
|
||||
}
|
||||
},
|
||||
confirm() {
|
||||
this.$store.commit('consent/set_consent', true)
|
||||
for (const elem in this.scopes) {
|
||||
if (this.scopes[elem].value === true) {
|
||||
this.$store.commit('consent/add_scope', elem)
|
||||
} else {
|
||||
this.$store.commit('consent/remove_scope', elem)
|
||||
}
|
||||
}
|
||||
this.$store.dispatch('consent/save', this.$cookies)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.card {
|
||||
@extend %card;
|
||||
padding: var(--spacing-card-lg);
|
||||
}
|
||||
.popup {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.spacer {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
.actions {
|
||||
margin-top: 1.5rem;
|
||||
margin-right: -0.5rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
.btn {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
}
|
||||
.consent-container {
|
||||
overflow-x: auto;
|
||||
max-height: 90vh;
|
||||
|
||||
@media screen and (min-width: 900px) {
|
||||
max-height: 50vh;
|
||||
}
|
||||
.h1 {
|
||||
font-size: 2rem;
|
||||
font-weight: bold;
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
.divider {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
.toggles {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
.toggle {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-bottom: 1rem;
|
||||
.toggle-text {
|
||||
.title {
|
||||
color: var(--color-text-dark);
|
||||
font-weight: bold;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.contents {
|
||||
color: var(--color-text);
|
||||
}
|
||||
}
|
||||
.spacer {
|
||||
flex-grow: 1;
|
||||
}
|
||||
.toggle-action {
|
||||
margin-left: 1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -63,7 +63,7 @@
|
||||
></pagination>
|
||||
</section>
|
||||
<div class="results column-grow-4">
|
||||
<Advertisement />
|
||||
<Advertisement ad-unit="banner" size="728x90,468x60" />
|
||||
<div v-if="results === null" class="no-results">
|
||||
<p>Loading...</p>
|
||||
</div>
|
||||
@ -279,7 +279,7 @@
|
||||
@input="toggleLicense"
|
||||
/>
|
||||
</div>
|
||||
<Advertisement format="rectangle" />
|
||||
<Advertisement ad-unit="square" size="250x250,200x200" />
|
||||
<m-footer class="footer" />
|
||||
</section>
|
||||
</div>
|
||||
@ -313,7 +313,7 @@ import FabricLoader from '~/assets/images/categories/fabric.svg?inline'
|
||||
import SearchIcon from '~/assets/images/utils/search.svg?inline'
|
||||
import ExitIcon from '~/assets/images/utils/exit.svg?inline'
|
||||
|
||||
import Advertisement from '~/components/Advertisement'
|
||||
import Advertisement from '~/components/ads/Advertisement'
|
||||
|
||||
export default {
|
||||
auth: false,
|
||||
|
||||
@ -55,11 +55,11 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Advertisement format="rectangle" />
|
||||
<Advertisement ad-unit="square" size="250x250,200x200" />
|
||||
<m-footer class="footer" />
|
||||
</div>
|
||||
<div class="content">
|
||||
<Advertisement />
|
||||
<Advertisement ad-unit="banner" size="728x90,468x60" />
|
||||
<div class="mods">
|
||||
<SearchResult
|
||||
v-for="result in mods"
|
||||
@ -89,7 +89,7 @@ import MFooter from '~/components/layout/MFooter'
|
||||
import ReportIcon from '~/assets/images/utils/report.svg?inline'
|
||||
import CalendarIcon from '~/assets/images/utils/calendar.svg?inline'
|
||||
import DownloadIcon from '~/assets/images/utils/download.svg?inline'
|
||||
import Advertisement from '~/components/Advertisement'
|
||||
import Advertisement from '~/components/ads/Advertisement'
|
||||
|
||||
export default {
|
||||
auth: false,
|
||||
|
||||
18
privacy-toggles.js
Normal file
18
privacy-toggles.js
Normal file
@ -0,0 +1,18 @@
|
||||
export default {
|
||||
settings: {
|
||||
ads: {
|
||||
title: 'Allow personalized ads',
|
||||
description: `Marketing/target cookies are usually used to show you advertisements that meet your interests.
|
||||
When you visit another website, your browser's cookie is recognized and selected ads are displayed to you
|
||||
based on the information stored in this cookie.`,
|
||||
default: false,
|
||||
},
|
||||
analytics: {
|
||||
title: 'Analytics',
|
||||
description: `Modrinth uses in-house tools that allows us to get insights on how
|
||||
each user is using the platform, to improve the experience for
|
||||
everyone.`,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
59
store/consent.js
Normal file
59
store/consent.js
Normal file
@ -0,0 +1,59 @@
|
||||
const VERSION = 1
|
||||
const parameters = {
|
||||
maxAge: 60 * 60 * 24 * 365 * 10, // Ten years
|
||||
sameSite: 'Strict',
|
||||
secure: true,
|
||||
httpOnly: false,
|
||||
path: '/',
|
||||
}
|
||||
|
||||
export const state = () => ({
|
||||
is_consent_given: false,
|
||||
scopes_allowed: [],
|
||||
loaded: false,
|
||||
})
|
||||
export const mutations = {
|
||||
loaded(state) {
|
||||
state.loaded = true
|
||||
},
|
||||
set_consent(state, val) {
|
||||
state.is_consent_given = val
|
||||
},
|
||||
add_scope(state, val) {
|
||||
// Check if the scope is not already provided
|
||||
if (state.scopes_allowed.includes(val)) return
|
||||
state.scopes_allowed.push(val)
|
||||
},
|
||||
remove_scope(state, val) {
|
||||
const pos = state.scopes_allowed.findIndex((el) => el === val)
|
||||
if (pos >= 0) state.scopes_allowed.splice(pos, 1)
|
||||
},
|
||||
}
|
||||
export const actions = {
|
||||
loadFromCookies(state, $cookies) {
|
||||
if (state.state.loaded) {
|
||||
return
|
||||
}
|
||||
state.commit('set_consent', $cookies.get('modrinth-consent') === true)
|
||||
const scopes = $cookies.get('modrinth-scopes')
|
||||
if (scopes == null) return
|
||||
scopes.split(',').forEach((elem) => {
|
||||
state.commit('add_scope', elem)
|
||||
})
|
||||
state.commit('loaded')
|
||||
},
|
||||
save(state, $cookies) {
|
||||
$cookies.set('modrinth-consent', state.state.is_consent_given, parameters)
|
||||
$cookies.set('modrinth-version', VERSION, parameters)
|
||||
$cookies.set(
|
||||
'modrinth-scopes',
|
||||
state.state.scopes_allowed.join(','),
|
||||
parameters
|
||||
)
|
||||
},
|
||||
}
|
||||
export const getters = {
|
||||
is_scope_allowed: (state) => (id) => {
|
||||
return state.scopes_allowed.contains(id)
|
||||
},
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user