Skip to content

Commit

Permalink
fix(vite): support iframe blocking (#88)
Browse files Browse the repository at this point in the history
Resolves #79

Co-authored-by: Jonas Thelemann <[email protected]>
  • Loading branch information
darioferderber and dargmuesli authored Jul 12, 2023
1 parent af05c06 commit 8ab8b7a
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 16 deletions.
12 changes: 11 additions & 1 deletion playground/app.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
<template>
<div>
<CookieControl :locale="locale" />
<CookieIframe :locale="locale" />

<iframe
src="https://player.vimeo.com/video/259622029?h=8dd8029ca1"
width="640"
height="480"
frameborder="0"
allow="autoplay; fullscreen; picture-in-picture"
allowfullscreen
>
</iframe>

<fieldset>
<legend>Choose a language</legend>
<div>
Expand Down
1 change: 1 addition & 0 deletions playground/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export default defineNuxtConfig({
],
},
isCookieIdVisible: true,
isIframeBlocked: true,
locales: ['en', 'de'],
localeTexts: {
de: {
Expand Down
21 changes: 20 additions & 1 deletion src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
defineNuxtModule,
addPlugin,
extendWebpackConfig,
extendViteConfig,
addTemplate,
addImports,
createResolver,
Expand All @@ -15,6 +16,7 @@ import { Nuxt } from '@nuxt/schema'

import { name, version } from '../package.json'
import { DEFAULTS, ModuleOptions } from './runtime/types'
import { replaceCodePlugin } from './replace'

const resolver = createResolver(import.meta.url)
const runtimeDir = resolver.resolve('./runtime')
Expand Down Expand Up @@ -94,7 +96,24 @@ const blockIframes = (moduleOptions: ModuleOptions) => {
},
})
})
// extendViteConfig(callback, options?)

extendViteConfig((config) => {
config?.plugins?.push(
replaceCodePlugin({
replacements: [
{
from: /<iframe[^>]*.*|<\/iframe>/g,
to: (match: string) =>
match.includes('cookie-enabled')
? match
: match
.replace(/<iframe/g, '<CookieIframe')
.replace(/iframe>/g, 'CookieIframe>'),
},
],
}),
)
})
}
}

Expand Down
50 changes: 50 additions & 0 deletions src/replace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// TODO: move to own library (https://github.com/leanupjs/vite-plugin-replace/pull/2)

const execSrcReplacements = (src: any, replacements: any[]) => {
for (const replacement of replacements) {
if (
(typeof replacement.from === 'string' ||
replacement.from instanceof RegExp) === false
) {
throw new TypeError(
"[vite-plugin-replace]: The replacement option 'from' is not of type 'string' or 'RegExp'.",
)
} else if (
(typeof replacement.to === 'string' ||
replacement.to instanceof Function) === false
) {
throw new TypeError(
"[vite-plugin-replace]: The replacement option 'to' is not of type 'string' or 'Function'",
)
} else src = src.replace(replacement.from, replacement.to)
}

return src
}

export const replaceCodePlugin = (config: any) => {
if (config === undefined) {
config = {
replacements: [],
}
} else if ((typeof config === 'object' || config !== null) === false) {
throw new TypeError(
"[vite-plugin-replace]: The configuration is not of type 'Object'.",
)
} else if (Array.isArray(config.replacements) === false) {
throw new TypeError(
"[vite-plugin-replace]: The configuration option 'replacement' is not of type 'Array'.",
)
}

return {
name: 'transform-file',
enforce: 'pre',
transform: function (src: any) {
return {
code: execSrcReplacements(src, config.replacements),
map: null,
}
},
} as any
}
15 changes: 15 additions & 0 deletions src/runtime/components/CookieControl.vue
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ const {
isModalActive,
moduleOptions,
} = useCookieControl()
const nuxtApp = useNuxtApp()
// data
const expires = new Date(Date.now() + moduleOptions.cookieExpiryOffsetMs)
Expand Down Expand Up @@ -278,6 +279,9 @@ const getName = (name: Translatable) => {
? localeStrings.value?.cookiesFunctional
: resolveTranslatable(name, props.locale)
}
const init = () => {
nuxtApp.$cookies.locale.value = props.locale
}
const onModalClick = () => {
if (moduleOptions.closeModalOnClickOutside) {
isModalActive.value = false
Expand Down Expand Up @@ -392,6 +396,7 @@ watch(
},
{ deep: true },
)
watch(isConsentGiven, (current, _previous) => {
if (current === undefined) {
cookieIsConsentGiven.value = undefined
Expand All @@ -400,6 +405,16 @@ watch(isConsentGiven, (current, _previous) => {
}
})
watch(
() => props.locale,
(locale) => {
nuxtApp.$cookies.locale.value = locale
},
)
// initialization
init()
defineExpose({
accept,
acceptPartial,
Expand Down
25 changes: 12 additions & 13 deletions src/runtime/components/CookieIframe.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
<template>
<client-only>
<iframe v-if="isCookieFunctionalEnabled" />
<ClientOnly>
<iframe
v-if="isCookieFunctionalEnabled"
:cookie-enabled="null"
v-bind="$attrs"
/>
<div v-else class="cookieControl__BlockedIframe">
<p>
{{ localeStrings?.iframeBlocked }}
Expand All @@ -11,25 +15,18 @@
/>
</p>
</div>
</client-only>
</ClientOnly>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import { LOCALE_DEFAULT } from '../constants'
import { Cookie, Locale } from '../types'
import { Cookie } from '../types'
import { useCookieControl } from '#imports'
export interface Props {
locale?: Locale
}
const props = withDefaults(defineProps<Props>(), {
locale: LOCALE_DEFAULT,
})
const { cookiesEnabled, isModalActive, moduleOptions } = useCookieControl()
const nuxtApp = useNuxtApp()
// computations
const isCookieFunctionalEnabled = computed(
Expand All @@ -38,5 +35,7 @@ const isCookieFunctionalEnabled = computed(
(cookieEnabled: Cookie) => cookieEnabled.name === 'functional',
).length > 0,
)
const localeStrings = computed(() => moduleOptions.localeTexts[props.locale])
const localeStrings = computed(
() => moduleOptions.localeTexts[nuxtApp.$cookies.locale.value],
)
</script>
4 changes: 3 additions & 1 deletion src/runtime/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@ export default defineNuxtPlugin((_nuxtApp) => {
)
const cookiesEnabledIds = ref<string[] | undefined>(cookieCookiesEnabledIds)
const isModalActive = ref<boolean>()
const locale = ref<string>()

const state = {
isConsentGiven,
cookiesEnabled,
cookiesEnabledIds,
isConsentGiven,
isModalActive,
locale,
moduleOptions,
} as State

Expand Down
1 change: 1 addition & 0 deletions src/runtime/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,5 +157,6 @@ export interface State {
cookiesEnabledIds: Ref<string[] | undefined>
isConsentGiven: Ref<boolean | undefined>
isModalActive: Ref<boolean>
locale: Ref<Locale>
moduleOptions: ModuleOptions
}

0 comments on commit 8ab8b7a

Please sign in to comment.