You've already forked AstralRinth
forked from didirus/AstralRinth
Added mobile friendly ads & ads (#161)
* Fix spacing issues on mobile * Added back linting on modules directory. Please don't look at the dirty fixes :x * Add support for responsive ads. * Add lazy loading of images.
This commit is contained in:
@@ -1,3 +1,2 @@
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
modules/*
|
||||
|
||||
@@ -1,25 +1,90 @@
|
||||
<template>
|
||||
<div class="ad-wrapper">
|
||||
<div class="ad">
|
||||
<GptAd :ad-unit="adUnit" :size="size" />
|
||||
<div v-if="displayed" class="ad">
|
||||
<GptAd
|
||||
:key="format.adUnit"
|
||||
ref="ad_slot"
|
||||
:ad-unit="format.adUnit"
|
||||
:size="format.size"
|
||||
:is-responsive="true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const sizes = {
|
||||
banner: {
|
||||
adUnit: 'banner',
|
||||
size: '728x90,468x60',
|
||||
},
|
||||
square: {
|
||||
adUnit: 'square',
|
||||
size: '250x250,200x200',
|
||||
},
|
||||
}
|
||||
|
||||
/* eslint-disable no-undef */
|
||||
export default {
|
||||
name: 'Advertisement',
|
||||
props: {
|
||||
size: {
|
||||
type: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
adUnit: {
|
||||
smallScreen: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
format: null,
|
||||
displayed: false,
|
||||
onSmallScreen: false,
|
||||
windowResizeListenerDebounce: null,
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
// Register hook on resize
|
||||
window.addEventListener('resize', this.handleWindowResize)
|
||||
|
||||
// Find ad
|
||||
if (!(this.type in sizes)) {
|
||||
console.error('Ad type not recognized.')
|
||||
return
|
||||
}
|
||||
// Set the informations
|
||||
this.format = sizes[this.type]
|
||||
this.displayed = true
|
||||
if (process.browser) {
|
||||
this.handleWindowResize()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleWindowResize() {
|
||||
clearTimeout(this.windowResizeListenerDebounce)
|
||||
this.windowResizeListenerDebounce = setTimeout(() => {
|
||||
if (window.innerWidth > 1024) {
|
||||
if (this.onSmallScreen) {
|
||||
// Return everything to normal size
|
||||
this.onSmallScreen = false
|
||||
this.format = sizes[this.type]
|
||||
this.displayed = true
|
||||
}
|
||||
return
|
||||
}
|
||||
this.onSmallScreen = true
|
||||
if (this.smallScreen === 'destroy') {
|
||||
this.displayed = false
|
||||
} else if (this.smallScreen in sizes) {
|
||||
console.log('Changing ad size to ', this.smallScreen)
|
||||
this.format = sizes[this.smallScreen]
|
||||
}
|
||||
}, 300)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -65,8 +65,8 @@
|
||||
</div>
|
||||
<Advertisement
|
||||
v-if="mod.status === 'approved' || mod.status === 'unlisted'"
|
||||
ad-unit="banner"
|
||||
size="728x90,468x60"
|
||||
type="banner"
|
||||
small-screen="square"
|
||||
/>
|
||||
<div class="mod-navigation">
|
||||
<div class="tabs">
|
||||
@@ -130,11 +130,6 @@
|
||||
</div>
|
||||
<div class="mod-content">
|
||||
<slot />
|
||||
<Advertisement
|
||||
v-if="mod.status === 'approved' || mod.status === 'unlisted'"
|
||||
ad-unit="banner"
|
||||
size="728x90,468x60"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<section class="mod-info">
|
||||
@@ -331,8 +326,8 @@
|
||||
</div>
|
||||
<Advertisement
|
||||
v-if="mod.status === 'approved' || mod.status === 'unlisted'"
|
||||
ad-unit="square"
|
||||
size="250x250,200x200"
|
||||
type="square"
|
||||
small-screen="destroy"
|
||||
/>
|
||||
<m-footer class="footer" />
|
||||
</section>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<img
|
||||
:src="iconUrl || 'https://cdn.modrinth.com/placeholder.svg?inline'"
|
||||
:alt="name"
|
||||
loading="lazy"
|
||||
/>
|
||||
</nuxt-link>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export const DEFAULT_OPTIONS = {
|
||||
enabled: false,
|
||||
script_url: 'https://example.com',
|
||||
tracking_code: 'xxx'
|
||||
enabled: false,
|
||||
script_url: 'https://example.com',
|
||||
tracking_code: 'xxx',
|
||||
}
|
||||
export const UNAMI_LIB_TAG_ID = 'unami-import'
|
||||
export const UNAMI_LIB_TAG_ID = 'unami-import'
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
import {
|
||||
DEFAULT_OPTIONS,
|
||||
UNAMI_LIB_TAG_ID
|
||||
} from './constants';
|
||||
import { DEFAULT_OPTIONS, UNAMI_LIB_TAG_ID } from './constants'
|
||||
|
||||
const { resolve } = require('path');
|
||||
const { resolve } = require('path')
|
||||
|
||||
// eslint-disable-next-line require-await
|
||||
module.exports = async function module(moduleOptions) {
|
||||
const options = Object.assign(DEFAULT_OPTIONS, this.options.analytics, 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');
|
||||
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')
|
||||
|
||||
@@ -1,64 +1,35 @@
|
||||
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;
|
||||
}
|
||||
if (cookies == null) return false
|
||||
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'));
|
||||
}
|
||||
|
||||
// eslint-disable-next-line require-await
|
||||
export default async function (ctx, inject) {
|
||||
const config = (ctx.$config && ctx.$config.analytics) || {}
|
||||
|
||||
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 %>;
|
||||
const url = config.script_url ?? '<%= options.script_url %>'
|
||||
const tag = config.tracking_code ?? '<%= options.tracking_code %>'
|
||||
// eslint-disable-next-line
|
||||
const enabled = config.enabled ?? ('<%= options.enabled || false %>' === 'true');
|
||||
// Check if the parameters are not changed by runtime config:
|
||||
|
||||
|
||||
|
||||
const UNAMI_LIB_TAG_ID = '<%= options.UNAMI_LIB_TAG_ID %>';
|
||||
|
||||
const UNAMI_LIB_TAG_ID = '<%= options.UNAMI_LIB_TAG_ID %>'
|
||||
|
||||
if (!enabled) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
const injectScript = (script) => {
|
||||
const scriptIndex = ctx.app.head.script.findIndex(s => s.hid === script.hid);
|
||||
const scriptIndex = ctx.app.head.script.findIndex(
|
||||
(s) => s.hid === script.hid
|
||||
)
|
||||
if (scriptIndex !== -1) {
|
||||
ctx.app.head.script[scriptIndex] = script;
|
||||
ctx.app.head.script[scriptIndex] = script
|
||||
} else {
|
||||
ctx.app.head.script.push(script);
|
||||
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.")
|
||||
// }
|
||||
|
||||
}
|
||||
const analyticsScript = {
|
||||
hid: UNAMI_LIB_TAG_ID,
|
||||
src: url,
|
||||
'data-website-id': tag,
|
||||
async: true,
|
||||
defer: true,
|
||||
}
|
||||
injectScript(analyticsScript)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ export const DEFAULT_OPTIONS = {
|
||||
responsive: false,
|
||||
collapseEmptyDivs: false,
|
||||
emptyClass: 'is-empty',
|
||||
geoEdgeId: ''
|
||||
};
|
||||
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';
|
||||
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'
|
||||
|
||||
@@ -4,12 +4,17 @@ import {
|
||||
GPT_INIT_SCRIPT_ID,
|
||||
GEOEDGE_CONF_SCRIPT_ID,
|
||||
GEOEDGE_LIB_SCRIPT_ID,
|
||||
} from './constants';
|
||||
} from './constants'
|
||||
|
||||
const { resolve } = require('path');
|
||||
const { resolve } = require('path')
|
||||
|
||||
// eslint-disable-next-line require-await
|
||||
module.exports = async function module(moduleOptions) {
|
||||
const options = Object.assign(DEFAULT_OPTIONS, this.options.ads, moduleOptions);
|
||||
const options = Object.assign(
|
||||
DEFAULT_OPTIONS,
|
||||
this.options.ads,
|
||||
moduleOptions
|
||||
)
|
||||
|
||||
const templatesOptions = {
|
||||
...options,
|
||||
@@ -17,18 +22,18 @@ module.exports = async function module(moduleOptions) {
|
||||
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');
|
||||
})
|
||||
}
|
||||
module.exports.meta = require('../package.json')
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-undef */
|
||||
export default {
|
||||
name: '<%= options.componentName %>',
|
||||
data: () => ({
|
||||
@@ -29,7 +30,7 @@ export default {
|
||||
isResponsive: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: <%= options.responsive %>,
|
||||
default: '<%= options.responsive %>' === 'true',
|
||||
},
|
||||
windowResizeDebounce: {
|
||||
type: Number,
|
||||
@@ -44,40 +45,42 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
ghostMode() {
|
||||
return this.$config.ads.ghostMode ?? <%= options.ghostMode %>;
|
||||
return this.$config.ads.ghostMode ?? '<%= options.ghostMode %>' === true
|
||||
},
|
||||
networkCode() {
|
||||
const { $gptAds } = this;
|
||||
return $gptAds ? $gptAds.networkCode : null;
|
||||
const { $gptAds } = this
|
||||
return $gptAds ? $gptAds.networkCode : null
|
||||
},
|
||||
adUnitPath() {
|
||||
const { networkCode, adUnit } = this;
|
||||
return `/${networkCode}/${adUnit}`;
|
||||
const { networkCode, adUnit } = this
|
||||
return `/${networkCode}/${adUnit}`
|
||||
},
|
||||
divId() {
|
||||
const { id } = this;
|
||||
return `div-gpt-ad-${id}-0`;
|
||||
const { id } = this
|
||||
return `div-gpt-ad-${id}-0`
|
||||
},
|
||||
formattedSize() {
|
||||
return this.formatSizeList(this.size);
|
||||
return this.formatSizeList(this.size)
|
||||
},
|
||||
style() {
|
||||
if (this.ghostMode) {
|
||||
const { formattedSize, currentSizeMappingIndex, mapping } = this;
|
||||
let baseSize = formattedSize;
|
||||
const { formattedSize, currentSizeMappingIndex, mapping } = this
|
||||
let baseSize = formattedSize
|
||||
if (currentSizeMappingIndex !== null) {
|
||||
baseSize = mapping[currentSizeMappingIndex][1];
|
||||
baseSize = mapping[currentSizeMappingIndex][1]
|
||||
}
|
||||
const size = Array.isArray(baseSize[0]) ? baseSize[0] : [baseSize[0], baseSize[1]];
|
||||
const [width, height] = size;
|
||||
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;
|
||||
return null
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
@@ -91,12 +94,12 @@ export default {
|
||||
*/
|
||||
formatSize(size) {
|
||||
if (Array.isArray(size)) {
|
||||
return size;
|
||||
return size
|
||||
}
|
||||
if (typeof size === 'string') {
|
||||
return size.split('x').map(value => parseInt(value, 10));
|
||||
return size.split('x').map((value) => parseInt(value, 10))
|
||||
}
|
||||
return [];
|
||||
return []
|
||||
},
|
||||
/**
|
||||
* Formats a given list of sizes to make it compatible with GPT API
|
||||
@@ -109,26 +112,25 @@ export default {
|
||||
*/
|
||||
formatSizeList(sizesList) {
|
||||
if (Array.isArray(sizesList)) {
|
||||
return sizesList;
|
||||
return sizesList
|
||||
}
|
||||
if (typeof sizesList === 'string') {
|
||||
return sizesList
|
||||
.split(',')
|
||||
.map(size => this.formatSize(size));
|
||||
return sizesList.split(',').map((size) => this.formatSize(size))
|
||||
}
|
||||
return [];
|
||||
return []
|
||||
},
|
||||
/**
|
||||
* Refresh ad slot
|
||||
*/
|
||||
refreshSlot() {
|
||||
googletag.pubads().refresh([this.adSlot]);
|
||||
console.log('Refreshing slot.')
|
||||
googletag.pubads().refresh([this.adSlot])
|
||||
},
|
||||
handleSlotRenderEnded (event) {
|
||||
handleSlotRenderEnded(event) {
|
||||
if (event.slot.getSlotId().getDomId() !== this.divId) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
this.isEmpty = !!event.isEmpty;
|
||||
this.isEmpty = !!event.isEmpty
|
||||
},
|
||||
/**
|
||||
* Window resize event listener
|
||||
@@ -137,17 +139,17 @@ export default {
|
||||
* the case
|
||||
*/
|
||||
handleWindowResize() {
|
||||
const { windowResizeDebounce } = this;
|
||||
clearTimeout(this.windowResizeListenerDebounce);
|
||||
const { windowResizeDebounce } = this
|
||||
clearTimeout(this.windowResizeListenerDebounce)
|
||||
this.windowResizeListenerDebounce = setTimeout(() => {
|
||||
const currentSizeMappingIndex = this.getCurrentSizeMappingIndex();
|
||||
const currentSizeMappingIndex = this.getCurrentSizeMappingIndex()
|
||||
if (currentSizeMappingIndex !== this.currentSizeMappingIndex) {
|
||||
if (!this.ghostMode) {
|
||||
this.refreshSlot();
|
||||
this.refreshSlot()
|
||||
}
|
||||
this.currentSizeMappingIndex = currentSizeMappingIndex;
|
||||
this.currentSizeMappingIndex = currentSizeMappingIndex
|
||||
}
|
||||
}, windowResizeDebounce);
|
||||
}, windowResizeDebounce)
|
||||
},
|
||||
/**
|
||||
* Gets the current size mapping index
|
||||
@@ -155,94 +157,96 @@ export default {
|
||||
* @return {Number} The current size mapping index
|
||||
*/
|
||||
getCurrentSizeMappingIndex() {
|
||||
const mapping = this.mapping || [];
|
||||
let index = null;
|
||||
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)`;
|
||||
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;
|
||||
index = i
|
||||
return true
|
||||
}
|
||||
return false;
|
||||
});
|
||||
return index;
|
||||
return false
|
||||
})
|
||||
return index
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (!window.googletag) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
const {
|
||||
ghostMode,
|
||||
adUnitPath,
|
||||
divId,
|
||||
sizeMapping,
|
||||
isResponsive,
|
||||
collapseEmptyDiv,
|
||||
} = this;
|
||||
|
||||
} = this
|
||||
|
||||
// Init Ad slot
|
||||
googletag.cmd.push(() => {
|
||||
const pubadsService = googletag.pubads()
|
||||
pubadsService.addEventListener('slotRenderEnded', this.handleSlotRenderEnded);
|
||||
pubadsService.setTargeting('path', this.$route.path);
|
||||
pubadsService.addEventListener(
|
||||
'slotRenderEnded',
|
||||
this.handleSlotRenderEnded
|
||||
)
|
||||
pubadsService.setTargeting('path', this.$route.path)
|
||||
|
||||
const adSlot = googletag
|
||||
.defineSlot(adUnitPath, this.formattedSize, divId)
|
||||
.addService(pubadsService);
|
||||
.addService(pubadsService)
|
||||
|
||||
// Collapse empty div slot-level override
|
||||
if (collapseEmptyDiv !== null) {
|
||||
adSlot.setCollapseEmptyDiv(collapseEmptyDiv);
|
||||
adSlot.setCollapseEmptyDiv(collapseEmptyDiv)
|
||||
}
|
||||
|
||||
// Build size mapping if any
|
||||
if (sizeMapping.length > 0) {
|
||||
const mapping = googletag.sizeMapping();
|
||||
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());
|
||||
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);
|
||||
const currentSizeMappingIndex = this.getCurrentSizeMappingIndex()
|
||||
this.currentSizeMappingIndex = currentSizeMappingIndex
|
||||
window.addEventListener('resize', this.handleWindowResize)
|
||||
}
|
||||
|
||||
this.adSlot = adSlot;
|
||||
this.$gptAds.slots.push(adSlot);
|
||||
this.adSlot = adSlot
|
||||
this.$gptAds.slots.push(adSlot)
|
||||
|
||||
if (!this.ghostMode) {
|
||||
googletag.display(divId);
|
||||
googletag.display(divId)
|
||||
if (this.$gptAds.individualRefresh) {
|
||||
this.refreshSlot();
|
||||
this.refreshSlot()
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
},
|
||||
beforeDestroy() {
|
||||
console.log('Destroying ad.')
|
||||
if (!googletag) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
// Destroy ad slot
|
||||
googletag.cmd.push(() => {
|
||||
const destroyed = googletag.destroySlots([this.adSlot]);
|
||||
});
|
||||
googletag.destroySlots([this.adSlot])
|
||||
})
|
||||
// Remove window resize listener
|
||||
window.removeEventListener('resize', this.handleWindowResize);
|
||||
window.removeEventListener('resize', this.handleWindowResize)
|
||||
},
|
||||
render(h) {
|
||||
const { divId, style, isEmpty } = this;
|
||||
let classAttr = isEmpty ? '<%= options.emptyClass %>' : '';
|
||||
const { divId, style, isEmpty } = this
|
||||
const classAttr = isEmpty ? '<%= options.emptyClass %>' : ''
|
||||
|
||||
return h('div', {
|
||||
style,
|
||||
@@ -251,6 +255,6 @@ export default {
|
||||
class: classAttr,
|
||||
},
|
||||
domProps: { innerHTML: '' },
|
||||
});
|
||||
})
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,71 +1,80 @@
|
||||
import Vue from 'vue';
|
||||
import Vue from 'vue'
|
||||
|
||||
function isPersonalizedAdsOn(ctx) {
|
||||
let cookies = []
|
||||
if (ctx.req != null) {
|
||||
//Server side rendering
|
||||
cookies = ctx.req.headers.cookie;
|
||||
// Server side rendering
|
||||
cookies = ctx.req.headers.cookie
|
||||
} else {
|
||||
// Rely on the client
|
||||
cookies = document.cookie;
|
||||
cookies = document.cookie
|
||||
}
|
||||
if (cookies == null) return false
|
||||
let processed = {}
|
||||
const processed = {}
|
||||
cookies.split(';').forEach((e) => {
|
||||
let val = e.trim().split('=')
|
||||
const val = e.trim().split('=')
|
||||
processed[val[0]] = decodeURI(val[1])
|
||||
})
|
||||
let scopes = decodeURIComponent(processed['modrinth-scopes']).split(",")
|
||||
return (scopes !== null && scopes.includes('ads'))
|
||||
const scopes = decodeURIComponent(processed['modrinth-scopes']).split(',')
|
||||
return scopes !== null && scopes.includes('ads')
|
||||
}
|
||||
|
||||
// eslint-disable-next-line require-await
|
||||
export default async function (ctx, inject) {
|
||||
|
||||
const { app } = ctx;
|
||||
const config = ctx.$config && ctx.$config.ads || {};
|
||||
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 %>';
|
||||
const debug = config.debug ?? '<%= options.debug || false %>' === 'true'
|
||||
const individualRefresh =
|
||||
config.individualRefresh ??
|
||||
'<%= options.individualRefresh || false %>' === 'true'
|
||||
const collapseEmptyDivs =
|
||||
config.collapseEmptyDivs ??
|
||||
'<%= options.collapseEmptyDivs || false %>' === 'true'
|
||||
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);
|
||||
const scriptIndex = ctx.app.head.script.findIndex(
|
||||
(s) => s.hid === script.hid
|
||||
)
|
||||
if (scriptIndex !== -1) {
|
||||
ctx.app.head.script[scriptIndex] = script;
|
||||
ctx.app.head.script[scriptIndex] = script
|
||||
} else {
|
||||
ctx.app.head.script.push(script);
|
||||
ctx.app.head.script.push(script)
|
||||
}
|
||||
};
|
||||
let no_consent = !isPersonalizedAdsOn(ctx)
|
||||
}
|
||||
const noConsent = !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']
|
||||
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);
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -74,20 +83,28 @@ export default async function (ctx, inject) {
|
||||
hid: GPT_LIB_SCRIPT_ID,
|
||||
src: 'https://www.googletagservices.com/tag/js/gpt.js',
|
||||
async: true,
|
||||
};
|
||||
injectScript(gptLibScript);
|
||||
}
|
||||
injectScript(gptLibScript)
|
||||
|
||||
// Inject GPT init script
|
||||
let gptInitScriptHtml = 'var googletag = googletag || {};googletag.cmd = googletag.cmd || [];';
|
||||
let gptInitScriptHtml =
|
||||
'var googletag = googletag || {};googletag.cmd = googletag.cmd || [];'
|
||||
if (debug) {
|
||||
gptInitScriptHtml += 'googletag.cmd.push(function(){googletag.openConsole();});';
|
||||
gptInitScriptHtml +=
|
||||
'googletag.cmd.push(function(){googletag.openConsole();});'
|
||||
}
|
||||
// Disable initial load
|
||||
const gptDisableInitialLoad = individualRefresh ? 'googletag.pubads().disableInitialLoad();' : '';
|
||||
const gptDisableInitialLoad = individualRefresh
|
||||
? 'googletag.pubads().disableInitialLoad();'
|
||||
: ''
|
||||
// Collapse empty div
|
||||
const gptCollapseEmptyDivs = collapseEmptyDivs ? 'googletag.pubads().collapseEmptyDivs();' : '';
|
||||
const gptCollapseEmptyDivs = collapseEmptyDivs
|
||||
? 'googletag.pubads().collapseEmptyDivs();'
|
||||
: ''
|
||||
// Desactivate personalization
|
||||
const gptDisablePersonalization = no_consent ? 'googletag.pubads().setRequestNonPersonalizedAds(1);' : '';
|
||||
const gptDisablePersonalization = noConsent
|
||||
? 'googletag.pubads().setRequestNonPersonalizedAds(1);'
|
||||
: ''
|
||||
gptInitScriptHtml += `
|
||||
googletag.cmd.push(function(){
|
||||
googletag.pubads().enableSingleRequest();
|
||||
@@ -96,17 +113,15 @@ export default async function (ctx, inject) {
|
||||
${gptDisablePersonalization}
|
||||
googletag.enableServices();
|
||||
});
|
||||
`;
|
||||
`
|
||||
const gptInitScript = {
|
||||
hid: GPT_INIT_SCRIPT_ID,
|
||||
innerHTML: gptInitScriptHtml,
|
||||
};
|
||||
injectScript(gptInitScript);
|
||||
}
|
||||
injectScript(gptInitScript)
|
||||
|
||||
const component = require('./component.js')
|
||||
Vue.component('<%= options.componentName %>', component.default || component)
|
||||
|
||||
const component = require('./component.js');
|
||||
Vue.component('<%= options.componentName %>', component.default || component);
|
||||
|
||||
inject('gptAds', gptAdsOptions);
|
||||
inject('gptAds', gptAdsOptions)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
"export": "nuxt export",
|
||||
"serve": "nuxt serve",
|
||||
"lint:js": "eslint --ext .js,.vue --ignore-path .eslintignore .",
|
||||
"lint": "npm run lint:js"
|
||||
"lint": "npm run lint:js",
|
||||
"fix": "eslint --fix --ext .js,.vue --ignore-path .eslintignore ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@nuxtjs/axios": "^5.12.5",
|
||||
|
||||
@@ -120,12 +120,14 @@ export default {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
.actions {
|
||||
margin-top: 1.5rem;
|
||||
margin-top: 1rem;
|
||||
margin-right: -0.5rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
flex-wrap: wrap;
|
||||
.btn {
|
||||
margin-top: 0.5rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
></pagination>
|
||||
</section>
|
||||
<div class="results column-grow-4">
|
||||
<Advertisement ad-unit="banner" size="728x90,468x60" />
|
||||
<Advertisement type="banner" small-screen="square" />
|
||||
<div v-if="results === null" class="no-results">
|
||||
<p>Loading...</p>
|
||||
</div>
|
||||
@@ -283,7 +283,7 @@
|
||||
@input="toggleLicense"
|
||||
/>
|
||||
</div>
|
||||
<Advertisement ad-unit="square" size="250x250,200x200" />
|
||||
<Advertisement type="square" small-screen="destroy" />
|
||||
<m-footer class="footer" hide-small />
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@@ -55,11 +55,11 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Advertisement ad-unit="square" size="250x250,200x200" />
|
||||
<Advertisement type="square" small-screen="square" />
|
||||
<m-footer class="footer" hide-small />
|
||||
</div>
|
||||
<div class="content">
|
||||
<Advertisement ad-unit="banner" size="728x90,468x60" />
|
||||
<Advertisement type="banner" small-screen="destroy" />
|
||||
<div class="mods">
|
||||
<SearchResult
|
||||
v-for="result in mods"
|
||||
|
||||
Reference in New Issue
Block a user