mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-08-04 03:27:05 -04:00
(nuxt) replace NUXT_PUBLIC_BASE_URL with calculating it from NUXT_PUBLIC_DOMAIN_BASE
This commit is contained in:
parent
dd5a8f49b0
commit
8959e84889
@ -1,7 +1,5 @@
|
|||||||
NUXT_PUBLIC_DOMAIN_BASE=http://{locale}.localhost:3000
|
NUXT_PUBLIC_DOMAIN_BASE=http://{locale}.localhost:3000
|
||||||
|
|
||||||
NUXT_PUBLIC_BASE_URL=http://localhost:3000
|
|
||||||
|
|
||||||
SECRET=changeMeOnProd!
|
SECRET=changeMeOnProd!
|
||||||
|
|
||||||
MAILER_TRANSPORT=
|
MAILER_TRANSPORT=
|
||||||
|
8
app.vue
8
app.vue
@ -1,15 +1,15 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useNuxtApp, useRuntimeConfig } from 'nuxt/app';
|
import { useNuxtApp } from 'nuxt/app';
|
||||||
|
|
||||||
import { useHead, useSeoMeta } from '#imports';
|
import { useHead, useSeoMeta } from '#imports';
|
||||||
import useConfig from '~/composables/useConfig.ts';
|
import useConfig from '~/composables/useConfig.ts';
|
||||||
import { getDefaultSeo } from '~/composables/useSimpleHead.ts';
|
import { getDefaultSeo } from '~/composables/useSimpleHead.ts';
|
||||||
|
import { getUrlForLocale } from '~/src/domain.ts';
|
||||||
|
|
||||||
const { $translator: translator } = useNuxtApp();
|
const { $translator: translator } = useNuxtApp();
|
||||||
const runtimeConfig = useRuntimeConfig();
|
|
||||||
const config = useConfig();
|
const config = useConfig();
|
||||||
|
|
||||||
const defaultSeo = getDefaultSeo(translator, runtimeConfig);
|
const defaultSeo = getDefaultSeo(config, translator);
|
||||||
const colour = '#C71585';
|
const colour = '#C71585';
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
@ -49,7 +49,7 @@ useSeoMeta({
|
|||||||
twitterCard: 'summary_large_image',
|
twitterCard: 'summary_large_image',
|
||||||
twitterTitle: defaultSeo.title,
|
twitterTitle: defaultSeo.title,
|
||||||
twitterDescription: defaultSeo.description,
|
twitterDescription: defaultSeo.description,
|
||||||
twitterSite: runtimeConfig.public.baseUrl,
|
twitterSite: getUrlForLocale(config.locale),
|
||||||
twitterImage: defaultSeo.banner,
|
twitterImage: defaultSeo.banner,
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -347,7 +347,7 @@ import { socialProviders } from '../src/socialProviders.ts';
|
|||||||
import { usernameRegex } from '../src/username.ts';
|
import { usernameRegex } from '../src/username.ts';
|
||||||
import { useMainStore } from '../store/index.ts';
|
import { useMainStore } from '../store/index.ts';
|
||||||
|
|
||||||
import { getUrlsForAllLocales } from '~/src/domain.ts';
|
import { getUrlForLocale, getUrlsForAllLocales } from '~/src/domain.ts';
|
||||||
import type { Profile } from '~/src/profile.ts';
|
import type { Profile } from '~/src/profile.ts';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
@ -371,11 +371,11 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const config = useConfig();
|
const config = useConfig();
|
||||||
const runtimeConfig = useRuntimeConfig();
|
const baseUrl = getUrlForLocale(config.locale);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
config,
|
config,
|
||||||
universalDomains: getUrlsForAllLocales(config.locale).filter((x) => x !== runtimeConfig.public.baseUrl),
|
universalDomains: getUrlsForAllLocales(config.locale).filter((url) => url !== baseUrl),
|
||||||
dialogue,
|
dialogue,
|
||||||
user,
|
user,
|
||||||
username: ref(user.value.username),
|
username: ref(user.value.username),
|
||||||
|
@ -3,6 +3,8 @@ import { EventLevel } from '../src/calendar/helpers.ts';
|
|||||||
import type { Event, Day } from '../src/calendar/helpers.ts';
|
import type { Event, Day } from '../src/calendar/helpers.ts';
|
||||||
import { newDate } from '../src/helpers.ts';
|
import { newDate } from '../src/helpers.ts';
|
||||||
|
|
||||||
|
import { getUrlForLocale } from '~/src/domain.ts';
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
event: Event;
|
event: Event;
|
||||||
year?: number;
|
year?: number;
|
||||||
@ -61,7 +63,7 @@ const eventParam = computed((): string | null => {
|
|||||||
<LinkedText v-else :text="eventName" />
|
<LinkedText v-else :text="eventName" />
|
||||||
<a
|
<a
|
||||||
v-if="ics && event.level !== EventLevel.CustomDay"
|
v-if="ics && event.level !== EventLevel.CustomDay"
|
||||||
:href="`/api/queer-calendar-${config.locale}-${year}-${event.getUuid($config.public.baseUrl)}.ics`"
|
:href="`/api/queer-calendar-${config.locale}-${year}-${event.getUuid(getUrlForLocale(config.locale))}.ics`"
|
||||||
class="small"
|
class="small"
|
||||||
:aria-label="`${$t('crud.download')} .ics`"
|
:aria-label="`${$t('crud.download')} .ics`"
|
||||||
:title="`${$t('crud.download')} .ics`"
|
:title="`${$t('crud.download')} .ics`"
|
||||||
|
@ -80,6 +80,8 @@ import useConfig from '../composables/useConfig.ts';
|
|||||||
import { socialLinks } from '../src/contact.ts';
|
import { socialLinks } from '../src/contact.ts';
|
||||||
import { clearUrl, newDate } from '../src/helpers.ts';
|
import { clearUrl, newDate } from '../src/helpers.ts';
|
||||||
|
|
||||||
|
import { getUrlForLocale } from '~/src/domain.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
day: {},
|
day: {},
|
||||||
@ -102,7 +104,7 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
icsLink() {
|
icsLink() {
|
||||||
const yearSuffix = this.year.year === newDate().getFullYear() ? '' : `-${this.year.year}`;
|
const yearSuffix = this.year.year === newDate().getFullYear() ? '' : `-${this.year.year}`;
|
||||||
return `${this.$config.public.baseUrl}/api/queer-calendar-${this.config.locale}${yearSuffix}.ics`;
|
return `${getUrlForLocale(this.config.locale)}/api/queer-calendar-${this.config.locale}${yearSuffix}.ics`;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,3 +1,30 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { getUrlForLocale } from '~/src/domain.ts';
|
||||||
|
|
||||||
|
const config = useConfig();
|
||||||
|
|
||||||
|
const exportStarted = ref(false);
|
||||||
|
const importSuccessful = ref(false);
|
||||||
|
|
||||||
|
const exportLink = computed(() => {
|
||||||
|
return `${getUrlForLocale(config.locale)}/api/profile/export`;
|
||||||
|
});
|
||||||
|
|
||||||
|
const importLink = computed(() => {
|
||||||
|
return `${getUrlForLocale(config.locale)}/api/profile/import`;
|
||||||
|
});
|
||||||
|
|
||||||
|
const startExport = () => {
|
||||||
|
exportStarted.value = true;
|
||||||
|
setTimeout(() => exportStarted.value = false, 5000);
|
||||||
|
};
|
||||||
|
|
||||||
|
const importDone = () => {
|
||||||
|
importSuccessful.value = true;
|
||||||
|
setTimeout(() => window.location.reload(), 3000);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section>
|
<section>
|
||||||
<h5>
|
<h5>
|
||||||
@ -37,32 +64,3 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
exportStarted: false,
|
|
||||||
importSuccessful: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
exportLink() {
|
|
||||||
return `${this.$config.public.baseUrl}/api/profile/export`;
|
|
||||||
},
|
|
||||||
importLink() {
|
|
||||||
return `${this.$config.public.baseUrl}/api/profile/import`;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
startExport() {
|
|
||||||
this.exportStarted = true;
|
|
||||||
setTimeout(() => this.exportStarted = false, 5000);
|
|
||||||
},
|
|
||||||
importDone() {
|
|
||||||
this.importSuccessful = true;
|
|
||||||
setTimeout(() => window.location.reload(), 3000);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
@ -2,11 +2,13 @@
|
|||||||
import { importSPKI, jwtVerify } from 'jose';
|
import { importSPKI, jwtVerify } from 'jose';
|
||||||
import type { FetchOptions } from 'ofetch';
|
import type { FetchOptions } from 'ofetch';
|
||||||
|
|
||||||
|
import { getUrlForLocale } from '~/src/domain.ts';
|
||||||
import { socialProviders } from '~/src/socialProviders.ts';
|
import { socialProviders } from '~/src/socialProviders.ts';
|
||||||
import type { User } from '~/src/user.ts';
|
import type { User } from '~/src/user.ts';
|
||||||
|
|
||||||
const { $setToken: setToken } = useNuxtApp();
|
const { $setToken: setToken } = useNuxtApp();
|
||||||
const runtimeConfig = useRuntimeConfig();
|
const runtimeConfig = useRuntimeConfig();
|
||||||
|
const config = useConfig();
|
||||||
|
|
||||||
const token = ref<string | null>(null);
|
const token = ref<string | null>(null);
|
||||||
const usernameOrEmail = ref('');
|
const usernameOrEmail = ref('');
|
||||||
@ -29,11 +31,12 @@ watchEffect(async () => {
|
|||||||
await setToken(token.value);
|
await setToken(token.value);
|
||||||
|
|
||||||
const importedPublicKey = await importSPKI(runtimeConfig.public.publicKey, 'RS256');
|
const importedPublicKey = await importSPKI(runtimeConfig.public.publicKey, 'RS256');
|
||||||
|
const baseUrl = getUrlForLocale(config.locale);
|
||||||
|
|
||||||
const result = await jwtVerify<User>(token.value, importedPublicKey, {
|
const result = await jwtVerify<User>(token.value, importedPublicKey, {
|
||||||
algorithms: ['RS256'],
|
algorithms: ['RS256'],
|
||||||
audience: runtimeConfig.public.baseUrl,
|
audience: baseUrl,
|
||||||
issuer: runtimeConfig.public.baseUrl,
|
issuer: baseUrl,
|
||||||
});
|
});
|
||||||
payload.value = result.payload;
|
payload.value = result.payload;
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { getUrlForLocale } from '~/src/domain.ts';
|
||||||
import { addSlash } from '~/src/helpers.ts';
|
import { addSlash } from '~/src/helpers.ts';
|
||||||
import { addPronounInjectionKey } from '~/src/injectionKeys.ts';
|
import { addPronounInjectionKey } from '~/src/injectionKeys.ts';
|
||||||
|
|
||||||
@ -11,7 +12,6 @@ const props = defineProps<{
|
|||||||
|
|
||||||
const addPronoun = inject(addPronounInjectionKey, undefined);
|
const addPronoun = inject(addPronounInjectionKey, undefined);
|
||||||
|
|
||||||
const runtimeConfig = useRuntimeConfig();
|
|
||||||
const config = useConfig();
|
const config = useConfig();
|
||||||
|
|
||||||
const open = ref(props.initiallyOpen ?? false);
|
const open = ref(props.initiallyOpen ?? false);
|
||||||
@ -21,7 +21,7 @@ const link = computed((): string | null => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return addSlash(`${runtimeConfig.public.baseUrl + (config.pronouns.prefix || '')}/${props.path}`);
|
return addSlash(`${getUrlForLocale(config.locale) + (config.pronouns.prefix || '')}/${props.path}`);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { useRuntimeConfig } from 'nuxt/app';
|
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
|
||||||
import { buildPronoun, buildPronounUsage } from '../src/buildPronoun.ts';
|
import { buildPronoun, buildPronounUsage } from '../src/buildPronoun.ts';
|
||||||
@ -9,6 +8,8 @@ import type { Translator } from '../src/translator';
|
|||||||
|
|
||||||
import useConfig from './useConfig.ts';
|
import useConfig from './useConfig.ts';
|
||||||
|
|
||||||
|
import { getUrlForLocale } from '~/src/domain.ts';
|
||||||
|
|
||||||
export interface PronounOpinion extends PronounUsage {
|
export interface PronounOpinion extends PronounUsage {
|
||||||
link: string;
|
link: string;
|
||||||
opinion: string;
|
opinion: string;
|
||||||
@ -19,7 +20,6 @@ export default (
|
|||||||
profile: Ref<Partial<Pick<Profile, 'pronouns'>> | null>,
|
profile: Ref<Partial<Pick<Profile, 'pronouns'>> | null>,
|
||||||
translator: Translator,
|
translator: Translator,
|
||||||
) => {
|
) => {
|
||||||
const runtimeConfig = useRuntimeConfig();
|
|
||||||
const config = useConfig();
|
const config = useConfig();
|
||||||
const pronouns = pronounLibrary.pronouns;
|
const pronouns = pronounLibrary.pronouns;
|
||||||
const pronounOpinions = computed((): PronounOpinion[] => {
|
const pronounOpinions = computed((): PronounOpinion[] => {
|
||||||
@ -28,10 +28,11 @@ export default (
|
|||||||
}
|
}
|
||||||
return (profile.value.pronouns ?? [])
|
return (profile.value.pronouns ?? [])
|
||||||
.map(({ value: pronoun, opinion }) => {
|
.map(({ value: pronoun, opinion }) => {
|
||||||
|
const baseUrl = getUrlForLocale(config.locale);
|
||||||
let link = pronoun
|
let link = pronoun
|
||||||
.trim()
|
.trim()
|
||||||
.replace(new RegExp(`^${runtimeConfig.public.baseUrl}`), '')
|
.replace(new RegExp(`^${baseUrl}`), '')
|
||||||
.replace(new RegExp(`^${runtimeConfig.public.baseUrl.replace(/^https?:\/\//, '')}`), '')
|
.replace(new RegExp(`^${baseUrl.replace(/^https?:\/\//, '')}`), '')
|
||||||
.replace(new RegExp('^/'), '');
|
.replace(new RegExp('^/'), '');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
import type { UseSeoMetaInput } from '@unhead/vue';
|
import type { UseSeoMetaInput } from '@unhead/vue';
|
||||||
import { useRuntimeConfig } from 'nuxt/app';
|
|
||||||
import type { RuntimeConfig } from 'nuxt/schema';
|
|
||||||
import { unref } from 'vue';
|
import { unref } from 'vue';
|
||||||
import type { MaybeRef } from 'vue';
|
import type { MaybeRef } from 'vue';
|
||||||
|
|
||||||
@ -8,12 +6,14 @@ import { clearLinkedText } from '../src/helpers.ts';
|
|||||||
import type { Translator } from '../src/translator';
|
import type { Translator } from '../src/translator';
|
||||||
|
|
||||||
import { useSeoMeta } from '#imports';
|
import { useSeoMeta } from '#imports';
|
||||||
|
import type { Config } from '~/locale/config.ts';
|
||||||
|
import { getUrlForLocale } from '~/src/domain.ts';
|
||||||
|
|
||||||
export const getDefaultSeo = (translator: Translator, runtimeConfig: RuntimeConfig) => ({
|
export const getDefaultSeo = (config: Config, translator: Translator) => ({
|
||||||
title: translator.translate('title'),
|
title: translator.translate('title'),
|
||||||
description: translator.translate('description'),
|
description: translator.translate('description'),
|
||||||
keywords: (translator.translate<string[]>('seo.keywords') || []).join(', '),
|
keywords: (translator.translate<string[]>('seo.keywords') || []).join(', '),
|
||||||
banner: `${runtimeConfig.public.baseUrl}/api/banner/zaimki.png`,
|
banner: `${getUrlForLocale(config.locale)}/api/banner/zaimki.png`,
|
||||||
});
|
});
|
||||||
|
|
||||||
export interface HeadParams {
|
export interface HeadParams {
|
||||||
@ -30,8 +30,8 @@ export default (
|
|||||||
{ title, description, banner, noindex = false, keywords }: HeadParams,
|
{ title, description, banner, noindex = false, keywords }: HeadParams,
|
||||||
translator: Translator,
|
translator: Translator,
|
||||||
): void => {
|
): void => {
|
||||||
const runtimeConfig = useRuntimeConfig();
|
const config = useConfig();
|
||||||
const defaultSeo = getDefaultSeo(translator, runtimeConfig);
|
const defaultSeo = getDefaultSeo(config, translator);
|
||||||
const seo: UseSeoMetaInput = {};
|
const seo: UseSeoMetaInput = {};
|
||||||
|
|
||||||
const seoTitle = () => {
|
const seoTitle = () => {
|
||||||
@ -66,6 +66,7 @@ export default (
|
|||||||
seo.ogDescription = seoDescription;
|
seo.ogDescription = seoDescription;
|
||||||
seo.twitterDescription = seoDescription;
|
seo.twitterDescription = seoDescription;
|
||||||
|
|
||||||
|
const baseUrl = getUrlForLocale(config.locale);
|
||||||
const seoImage = () => {
|
const seoImage = () => {
|
||||||
let bannerUnwrapped = unref(banner);
|
let bannerUnwrapped = unref(banner);
|
||||||
if (!bannerUnwrapped) {
|
if (!bannerUnwrapped) {
|
||||||
@ -73,7 +74,7 @@ export default (
|
|||||||
}
|
}
|
||||||
bannerUnwrapped = bannerUnwrapped.replace(/^\//, '');
|
bannerUnwrapped = bannerUnwrapped.replace(/^\//, '');
|
||||||
if (!bannerUnwrapped.startsWith('https://')) {
|
if (!bannerUnwrapped.startsWith('https://')) {
|
||||||
bannerUnwrapped = `${runtimeConfig.public.baseUrl}/${bannerUnwrapped}`;
|
bannerUnwrapped = `${baseUrl}/${bannerUnwrapped}`;
|
||||||
}
|
}
|
||||||
return bannerUnwrapped;
|
return bannerUnwrapped;
|
||||||
};
|
};
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
import { useRuntimeConfig } from 'nuxt/app';
|
|
||||||
|
|
||||||
import { useMainStore } from '../store/index.ts';
|
import { useMainStore } from '../store/index.ts';
|
||||||
|
|
||||||
import { getUrlForLocale } from '~/src/domain.ts';
|
import { getUrlForLocale } from '~/src/domain.ts';
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const runtimeConfig = useRuntimeConfig();
|
|
||||||
const store = useMainStore();
|
const store = useMainStore();
|
||||||
|
|
||||||
const buildSocialLoginConnectLink = (
|
const buildSocialLoginConnectLink = (
|
||||||
@ -16,7 +13,7 @@ export default () => {
|
|||||||
): string => {
|
): string => {
|
||||||
const url = providerOptions.redirectViaHome
|
const url = providerOptions.redirectViaHome
|
||||||
? new URL(`/api/user/social-redirect/${provider}/${locale}`, getUrlForLocale('_'))
|
? new URL(`/api/user/social-redirect/${provider}/${locale}`, getUrlForLocale('_'))
|
||||||
: new URL(`/api/connect/${provider}`, runtimeConfig.public.baseUrl);
|
: new URL(`/api/connect/${provider}`, getUrlForLocale(locale));
|
||||||
|
|
||||||
if (providerOptions.instanceRequired && instance) {
|
if (providerOptions.instanceRequired && instance) {
|
||||||
url.searchParams.append('instance', instance ?? '');
|
url.searchParams.append('instance', instance ?? '');
|
||||||
|
@ -79,7 +79,6 @@ export default defineNuxtConfig({
|
|||||||
public: {
|
public: {
|
||||||
domainBase: undefined as string | undefined,
|
domainBase: undefined as string | undefined,
|
||||||
env: 'home',
|
env: 'home',
|
||||||
baseUrl: 'https://pronouns.page',
|
|
||||||
version,
|
version,
|
||||||
publicKey: '',
|
publicKey: '',
|
||||||
turnstileSitekey: '',
|
turnstileSitekey: '',
|
||||||
|
@ -3,6 +3,7 @@ import { useNuxtApp } from 'nuxt/app';
|
|||||||
|
|
||||||
import useConfig from '~/composables/useConfig.ts';
|
import useConfig from '~/composables/useConfig.ts';
|
||||||
import useSimpleHead from '~/composables/useSimpleHead.ts';
|
import useSimpleHead from '~/composables/useSimpleHead.ts';
|
||||||
|
import { getUrlForLocale } from '~/src/domain.ts';
|
||||||
|
|
||||||
interface Group {
|
interface Group {
|
||||||
enabled: boolean | undefined;
|
enabled: boolean | undefined;
|
||||||
@ -120,7 +121,7 @@ const groups = computed((): Group[] => {
|
|||||||
<code>{{ path }}</code>
|
<code>{{ path }}</code>
|
||||||
<a
|
<a
|
||||||
v-for="example in config.api.examples[endpoint]"
|
v-for="example in config.api.examples[endpoint]"
|
||||||
:href="$config.public.baseUrl + example"
|
:href="getUrlForLocale(config.locale) + example"
|
||||||
class="badge bg-light text-dark border mx-1"
|
class="badge bg-light text-dark border mx-1"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
|
@ -8,6 +8,7 @@ import type { LocaleDescription } from '~/locale/locales.ts';
|
|||||||
import type { TermsEntryRaw } from '~/src/classes.ts';
|
import type { TermsEntryRaw } from '~/src/classes.ts';
|
||||||
import { longtimeCookieSetting } from '~/src/cookieSettings.ts';
|
import { longtimeCookieSetting } from '~/src/cookieSettings.ts';
|
||||||
import { loadPronounLibrary } from '~/src/data.ts';
|
import { loadPronounLibrary } from '~/src/data.ts';
|
||||||
|
import { getUrlForLocale } from '~/src/domain.ts';
|
||||||
import { buildFlags } from '~/src/flags.ts';
|
import { buildFlags } from '~/src/flags.ts';
|
||||||
import { sleep } from '~/src/helpers.ts';
|
import { sleep } from '~/src/helpers.ts';
|
||||||
import opinions from '~/src/opinions.ts';
|
import opinions from '~/src/opinions.ts';
|
||||||
@ -110,9 +111,8 @@ const verifiedLinks = computed(() => {
|
|||||||
.flat())];
|
.flat())];
|
||||||
});
|
});
|
||||||
|
|
||||||
const runtimeConfig = useRuntimeConfig();
|
|
||||||
const icsLink = computed(() => {
|
const icsLink = computed(() => {
|
||||||
return `${runtimeConfig.public.baseUrl}/api/queer-calendar-${config.locale}-@${username.value}.ics`;
|
return `${getUrlForLocale(config.locale)}/api/queer-calendar-${config.locale}-@${username.value}.ics`;
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
@ -12,6 +12,7 @@ import type { Config } from '~/locale/config.ts';
|
|||||||
import { birthdateRange, formatDate, parseDate } from '~/src/birthdate.ts';
|
import { birthdateRange, formatDate, parseDate } from '~/src/birthdate.ts';
|
||||||
import { buildPronounUsage } from '~/src/buildPronoun.ts';
|
import { buildPronounUsage } from '~/src/buildPronoun.ts';
|
||||||
import { loadCalendar, loadPronounLibrary } from '~/src/data.ts';
|
import { loadCalendar, loadPronounLibrary } from '~/src/data.ts';
|
||||||
|
import { getUrlForLocale } from '~/src/domain.ts';
|
||||||
import { buildList, isValidLink } from '~/src/helpers.ts';
|
import { buildList, isValidLink } from '~/src/helpers.ts';
|
||||||
import { addPronounInjectionKey } from '~/src/injectionKeys.ts';
|
import { addPronounInjectionKey } from '~/src/injectionKeys.ts';
|
||||||
import opinions from '~/src/opinions.ts';
|
import opinions from '~/src/opinions.ts';
|
||||||
@ -222,7 +223,6 @@ const visibilityIcons = {
|
|||||||
[ProfileVisibility.Internal]: ['user-shield'],
|
[ProfileVisibility.Internal]: ['user-shield'],
|
||||||
} as Record<ProfileVisibility, string[]>;
|
} as Record<ProfileVisibility, string[]>;
|
||||||
|
|
||||||
const runtimeConfig = useRuntimeConfig();
|
|
||||||
const year = (await loadCalendar()).getCurrentYear();
|
const year = (await loadCalendar()).getCurrentYear();
|
||||||
|
|
||||||
const { mainPronoun } = useMainPronoun(pronounLibrary, formData, translator);
|
const { mainPronoun } = useMainPronoun(pronounLibrary, formData, translator);
|
||||||
@ -282,12 +282,13 @@ const save = async (): Promise<void> => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const normalisePronoun = (pronoun: string): string | null => {
|
const normalisePronoun = (pronoun: string): string | null => {
|
||||||
|
const baseUrl = getUrlForLocale(config.locale);
|
||||||
try {
|
try {
|
||||||
return decodeURIComponent(pronoun
|
return decodeURIComponent(pronoun
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.trim()
|
.trim()
|
||||||
.replace(new RegExp(`^${runtimeConfig.public.baseUrl}`), '')
|
.replace(new RegExp(`^${baseUrl}`), '')
|
||||||
.replace(new RegExp(`^${runtimeConfig.public.baseUrl.replace(/^https?:\/\//, '')}`), '')
|
.replace(new RegExp(`^${baseUrl.replace(/^https?:\/\//, '')}`), '')
|
||||||
.replace(new RegExp('^/'), ''));
|
.replace(new RegExp('^/'), ''));
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
|
@ -9,13 +9,13 @@ import type { Config } from '../locale/config.ts';
|
|||||||
|
|
||||||
import dbConnection from './db.ts';
|
import dbConnection from './db.ts';
|
||||||
|
|
||||||
import { loadSuml } from '~/server/loader.ts';
|
import localeDescriptions from '~/locale/locales.ts';
|
||||||
|
import { loadConfig } from '~/server/data.ts';
|
||||||
import { buildCalendar } from '~/src/calendar/calendar.ts';
|
import { buildCalendar } from '~/src/calendar/calendar.ts';
|
||||||
|
import { getLocaleUrls } from '~/src/domain.ts';
|
||||||
|
|
||||||
const __dirname = new URL('.', import.meta.url).pathname;
|
const __dirname = new URL('.', import.meta.url).pathname;
|
||||||
|
|
||||||
const config = loadSuml('config') as Config;
|
|
||||||
|
|
||||||
const force = process.argv[2] === '-f' || process.argv[2] === '--force';
|
const force = process.argv[2] === '-f' || process.argv[2] === '--force';
|
||||||
|
|
||||||
const shoot = async (url: string, filename: string): Promise<void> => {
|
const shoot = async (url: string, filename: string): Promise<void> => {
|
||||||
@ -26,7 +26,7 @@ const shoot = async (url: string, filename: string): Promise<void> => {
|
|||||||
headless: 'new',
|
headless: 'new',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
pr.source(process.env.NUXT_PUBLIC_BASE_URL + url, ['1500x300']);
|
pr.source(url, ['1500x300']);
|
||||||
for (const buffer of await pr.run()) {
|
for (const buffer of await pr.run()) {
|
||||||
fs.mkdirSync(path.dirname(filename), { recursive: true });
|
fs.mkdirSync(path.dirname(filename), { recursive: true });
|
||||||
console.log(filename);
|
console.log(filename);
|
||||||
@ -34,7 +34,7 @@ const shoot = async (url: string, filename: string): Promise<void> => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const dumpNameDays = async (): Promise<void> => {
|
const dumpNameDays = async (config: Config): Promise<void> => {
|
||||||
if (!config.names || !config.names.enabled || !config.names.namedays) {
|
if (!config.names || !config.names.enabled || !config.names.namedays) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -53,7 +53,7 @@ const dumpNameDays = async (): Promise<void> => {
|
|||||||
fs.writeFileSync(`${__dirname}/../locale/${config.locale}/names/namedays.json`, JSON.stringify(output));
|
fs.writeFileSync(`${__dirname}/../locale/${config.locale}/names/namedays.json`, JSON.stringify(output));
|
||||||
};
|
};
|
||||||
|
|
||||||
(async (): Promise<void> => {
|
const run = async (config: Config, baseUrl: string): Promise<void> => {
|
||||||
if (!config.calendar?.enabled) {
|
if (!config.calendar?.enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ const dumpNameDays = async (): Promise<void> => {
|
|||||||
for (const day of Object.keys(current)) {
|
for (const day of Object.keys(current)) {
|
||||||
const year = day.substring(0, 4);
|
const year = day.substring(0, 4);
|
||||||
if (current[day] !== prev[day] || !fs.existsSync(`${dir}/${day}.png`) || force) {
|
if (current[day] !== prev[day] || !fs.existsSync(`${dir}/${day}.png`) || force) {
|
||||||
await shoot(`/${config.calendar.route}/${day}?layout=basic`, `${dir}/${day}.png`);
|
await shoot(`${baseUrl}/${config.calendar.route}/${day}?layout=basic`, `${dir}/${day}.png`);
|
||||||
changedYears.add(year);
|
changedYears.add(year);
|
||||||
}
|
}
|
||||||
if (!fs.existsSync(`${dir}/${year}-overview.png`) || !fs.existsSync(`${dir}/${year}-labels.png`) || force) {
|
if (!fs.existsSync(`${dir}/${year}-overview.png`) || !fs.existsSync(`${dir}/${year}-labels.png`) || force) {
|
||||||
@ -78,11 +78,25 @@ const dumpNameDays = async (): Promise<void> => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const year of changedYears) {
|
for (const year of changedYears) {
|
||||||
await shoot(`/${config.calendar.route}/${year}?layout=basic`, `${dir}/${year}-overview.png`);
|
await shoot(
|
||||||
await shoot(`/${config.calendar.route}/${year}?layout=basic&labels=true`, `${dir}/${year}-labels.png`);
|
`${baseUrl}/${config.calendar.route}/${year}?layout=basic`,
|
||||||
|
`${dir}/${year}-overview.png`,
|
||||||
|
);
|
||||||
|
await shoot(
|
||||||
|
`${baseUrl}/${config.calendar.route}/${year}?layout=basic&labels=true`,
|
||||||
|
`${dir}/${year}-labels.png`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFileSync(prevPath, JSON.stringify(current, null, 4));
|
fs.writeFileSync(prevPath, JSON.stringify(current, null, 4));
|
||||||
|
|
||||||
await dumpNameDays();
|
await dumpNameDays(config);
|
||||||
|
};
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const localeUrls = getLocaleUrls(process.env.NUXT_PUBLIC_DOMAIN_BASE);
|
||||||
|
for (const localeDescription of localeDescriptions) {
|
||||||
|
const config = await loadConfig(localeDescription.code);
|
||||||
|
await run(config, localeUrls[config.locale]);
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
|
@ -6,28 +6,20 @@ import Pageres from 'pageres';
|
|||||||
import type { Screenshot } from 'pageres';
|
import type { Screenshot } from 'pageres';
|
||||||
import { ulid } from 'ulid';
|
import { ulid } from 'ulid';
|
||||||
|
|
||||||
import allLocales from '../locale/locales.ts';
|
|
||||||
|
|
||||||
import { awsConfig, awsParams } from './aws.ts';
|
import { awsConfig, awsParams } from './aws.ts';
|
||||||
import dbConnection from './db.ts';
|
import dbConnection from './db.ts';
|
||||||
import type { Database } from './db.ts';
|
import type { Database } from './db.ts';
|
||||||
import { env } from './env.ts';
|
|
||||||
import isHighLoadTime from './overload.js';
|
import isHighLoadTime from './overload.js';
|
||||||
|
|
||||||
import jwt from '~/server/jwt.ts';
|
import jwt from '~/server/jwt.ts';
|
||||||
|
import { getUrlsForAllLocales } from '~/src/domain.ts';
|
||||||
|
|
||||||
const s3 = new S3(awsConfig);
|
const s3 = new S3(awsConfig);
|
||||||
|
|
||||||
const urlBases: Record<string, string> = {};
|
const urlBases: Record<string, string> = {};
|
||||||
|
|
||||||
if ((env === 'development' || process.env.NUXT_PUBLIC_ENV === 'test') && process.env.NUXT_PUBLIC_BASE_URL) {
|
for (const [locale, url] of Object.entries(getUrlsForAllLocales('_', true))) {
|
||||||
for (const { code } of allLocales) {
|
urlBases[locale] = `${url}/card/@`;
|
||||||
urlBases[code] = `${process.env.NUXT_PUBLIC_BASE_URL}/card/@`;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (const { code, url } of allLocales) {
|
|
||||||
urlBases[code] = `${url}/card/@`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const sleep = (ms: number): Promise<void> => new Promise((res) => setTimeout(res, ms));
|
const sleep = (ms: number): Promise<void> => new Promise((res) => setTimeout(res, ms));
|
||||||
|
@ -10,7 +10,7 @@ import { buildCalendar } from '~/src/calendar/calendar.ts';
|
|||||||
import type { Calendar } from '~/src/calendar/helpers.ts';
|
import type { Calendar } from '~/src/calendar/helpers.ts';
|
||||||
import { PronounLibrary } from '~/src/classes.ts';
|
import { PronounLibrary } from '~/src/classes.ts';
|
||||||
import type { Pronoun, PronounGroup } from '~/src/classes.ts';
|
import type { Pronoun, PronounGroup } from '~/src/classes.ts';
|
||||||
import { getLocaleForUrl } from '~/src/domain.ts';
|
import { getLocaleForUrl, getUrlForLocale } from '~/src/domain.ts';
|
||||||
import { Translator } from '~/src/translator.ts';
|
import { Translator } from '~/src/translator.ts';
|
||||||
import { loadTsv } from '~/src/tsv.ts';
|
import { loadTsv } from '~/src/tsv.ts';
|
||||||
|
|
||||||
@ -81,8 +81,7 @@ export const loadPronounExamples = async (locale: string): Promise<PronounExampl
|
|||||||
const calendarByLocale: Map<string, Calendar> = new Map();
|
const calendarByLocale: Map<string, Calendar> = new Map();
|
||||||
export const loadCalendar = async (locale: string): Promise<Calendar> => {
|
export const loadCalendar = async (locale: string): Promise<Calendar> => {
|
||||||
return setDefault(calendarByLocale, locale, async () => {
|
return setDefault(calendarByLocale, locale, async () => {
|
||||||
const runtimeConfig = useRuntimeConfig();
|
|
||||||
const localEvents = await localeEventImports[locale]();
|
const localEvents = await localeEventImports[locale]();
|
||||||
return buildCalendar(localEvents, runtimeConfig.public.baseUrl);
|
return buildCalendar(localEvents, getUrlForLocale(locale));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -7,7 +7,7 @@ import type { KeyLike, JWTPayload } from 'jose';
|
|||||||
|
|
||||||
import { rootDir } from './paths.ts';
|
import { rootDir } from './paths.ts';
|
||||||
|
|
||||||
import { getUrlsForAllLocales } from '~/src/domain.ts';
|
import { getUrlForLocale, getUrlsForAllLocales } from '~/src/domain.ts';
|
||||||
|
|
||||||
class Jwt {
|
class Jwt {
|
||||||
constructor(private privateKey: KeyLike, private publicKey: KeyLike) {}
|
constructor(private privateKey: KeyLike, private publicKey: KeyLike) {}
|
||||||
@ -26,7 +26,7 @@ class Jwt {
|
|||||||
.setProtectedHeader({ alg: 'RS256' })
|
.setProtectedHeader({ alg: 'RS256' })
|
||||||
.setExpirationTime(expiresIn)
|
.setExpirationTime(expiresIn)
|
||||||
.setAudience(getUrlsForAllLocales(locale))
|
.setAudience(getUrlsForAllLocales(locale))
|
||||||
.setIssuer(process.env.NUXT_PUBLIC_BASE_URL!)
|
.setIssuer(getUrlForLocale(locale))
|
||||||
.sign(this.privateKey);
|
.sign(this.privateKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,23 +3,24 @@ import marked from 'marked';
|
|||||||
|
|
||||||
import { getPosts } from '~/server/blog.ts';
|
import { getPosts } from '~/server/blog.ts';
|
||||||
import { getLocale, loadConfig, loadTranslator } from '~/server/data.ts';
|
import { getLocale, loadConfig, loadTranslator } from '~/server/data.ts';
|
||||||
|
import { getUrlForLocale } from '~/src/domain.ts';
|
||||||
import parseMarkdown from '~/src/parseMarkdown.ts';
|
import parseMarkdown from '~/src/parseMarkdown.ts';
|
||||||
|
|
||||||
export default defineCachedEventHandler(async (event) => {
|
export default defineCachedEventHandler(async (event) => {
|
||||||
const runtimeConfig = useRuntimeConfig();
|
|
||||||
const locale = getLocale(event);
|
const locale = getLocale(event);
|
||||||
const [config, translator] = await Promise.all([loadConfig(locale), loadTranslator(locale)]);
|
const [config, translator] = await Promise.all([loadConfig(locale), loadTranslator(locale)]);
|
||||||
|
|
||||||
|
const baseUrl = getUrlForLocale(locale);
|
||||||
const posts = await getPosts(config);
|
const posts = await getPosts(config);
|
||||||
|
|
||||||
const feed = new Feed({
|
const feed = new Feed({
|
||||||
title: `${translator.translate('title')} • ${translator.translate('links.blog')}`,
|
title: `${translator.translate('title')} • ${translator.translate('links.blog')}`,
|
||||||
description: translator.translate('description'),
|
description: translator.translate('description'),
|
||||||
id: runtimeConfig.public.baseUrl,
|
id: baseUrl,
|
||||||
link: `${runtimeConfig.public.baseUrl}/blog.atom`,
|
link: `${baseUrl}/blog.atom`,
|
||||||
language: config.locale,
|
language: config.locale,
|
||||||
image: `${runtimeConfig.public.baseUrl}/icon.png`,
|
image: `${baseUrl}/icon.png`,
|
||||||
favicon: `${runtimeConfig.public.baseUrl}/icon.png`,
|
favicon: `${baseUrl}/icon.png`,
|
||||||
updated: new Date(posts[0].date),
|
updated: new Date(posts[0].date),
|
||||||
copyright: '',
|
copyright: '',
|
||||||
});
|
});
|
||||||
@ -30,16 +31,16 @@ export default defineCachedEventHandler(async (event) => {
|
|||||||
|
|
||||||
feed.addItem({
|
feed.addItem({
|
||||||
title: post.title,
|
title: post.title,
|
||||||
id: `${runtimeConfig.public.baseUrl}/${config.links.blogRoute}/${post.slug}`,
|
id: `${baseUrl}/${config.links.blogRoute}/${post.slug}`,
|
||||||
link: `${runtimeConfig.public.baseUrl}/${config.links.blogRoute}/${post.slug}`,
|
link: `${baseUrl}/${config.links.blogRoute}/${post.slug}`,
|
||||||
description: parsed.intro ?? undefined,
|
description: parsed.intro ?? undefined,
|
||||||
content: parsed.content ?? undefined,
|
content: parsed.content ?? undefined,
|
||||||
author: post.authors.map((author) => ({
|
author: post.authors.map((author) => ({
|
||||||
name: author,
|
name: author,
|
||||||
link: author.startsWith('@') ? `${runtimeConfig.public.baseUrl}/${author}` : undefined,
|
link: author.startsWith('@') ? `${baseUrl}/${author}` : undefined,
|
||||||
})),
|
})),
|
||||||
date: new Date(post.date),
|
date: new Date(post.date),
|
||||||
image: post.hero ? `${runtimeConfig.public.baseUrl}${post.hero.src}` : undefined,
|
image: post.hero ? `${baseUrl}${post.hero.src}` : undefined,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@ import { importPKCS8, SignJWT } from 'jose';
|
|||||||
|
|
||||||
import { rootDir } from './paths.ts';
|
import { rootDir } from './paths.ts';
|
||||||
|
|
||||||
|
import { getUrlForLocale } from '~/src/domain.ts';
|
||||||
|
|
||||||
const getAppleClientSecret = async (): Promise<string | undefined> => {
|
const getAppleClientSecret = async (): Promise<string | undefined> => {
|
||||||
const headers = {
|
const headers = {
|
||||||
alg: 'ES256',
|
alg: 'ES256',
|
||||||
@ -61,7 +63,7 @@ const enableApple = appleIsEnabled();
|
|||||||
|
|
||||||
export const config: GrantConfig = {
|
export const config: GrantConfig = {
|
||||||
defaults: {
|
defaults: {
|
||||||
origin: process.env.NUXT_PUBLIC_BASE_URL,
|
origin: getUrlForLocale('_'),
|
||||||
transport: 'session',
|
transport: 'session',
|
||||||
state: true,
|
state: true,
|
||||||
prefix: '/api/connect',
|
prefix: '/api/connect',
|
||||||
|
@ -6,7 +6,7 @@ import type { Config } from '~/locale/config.ts';
|
|||||||
import type { PronounExamplesData } from '~/locale/data.ts';
|
import type { PronounExamplesData } from '~/locale/data.ts';
|
||||||
import type { Translations } from '~/locale/translations.ts';
|
import type { Translations } from '~/locale/translations.ts';
|
||||||
import { buildCalendar } from '~/src/calendar/calendar.ts';
|
import { buildCalendar } from '~/src/calendar/calendar.ts';
|
||||||
import { getLocaleForUrl } from '~/src/domain.ts';
|
import { getLocaleForUrl, getUrlForLocale } from '~/src/domain.ts';
|
||||||
|
|
||||||
export const getLocale = () => {
|
export const getLocale = () => {
|
||||||
return getLocaleForUrl(useRequestURL()) ?? '_';
|
return getLocaleForUrl(useRequestURL()) ?? '_';
|
||||||
@ -110,8 +110,9 @@ export const loadNameCount = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const loadCalendar = async () => {
|
export const loadCalendar = async () => {
|
||||||
const runtimeConfig = useRuntimeConfig();
|
const locale = getLocale();
|
||||||
const localEvents = (await import(`~/locale/${getLocale()}/calendar/events.ts`)).default;
|
const baseUrl = getUrlForLocale(locale);
|
||||||
|
const localEvents = (await import(`~/locale/${locale}/calendar/events.ts`)).default;
|
||||||
/* const rawNamedays = (await import(`~/locale/${config.locale}/names/namedays.json`)).default;
|
/* const rawNamedays = (await import(`~/locale/${config.locale}/names/namedays.json`)).default;
|
||||||
const namedays = Object.entries(rawNamedays as Record<string, string[]>)
|
const namedays = Object.entries(rawNamedays as Record<string, string[]>)
|
||||||
.flatMap(([name, namedays]) => {
|
.flatMap(([name, namedays]) => {
|
||||||
@ -120,5 +121,5 @@ export const loadCalendar = async () => {
|
|||||||
return new Event(`nameday$${name}`, null, parseInt(m), day(parseInt(d)), EventLevel.Nameday);
|
return new Event(`nameday$${name}`, null, parseInt(m), day(parseInt(d)), EventLevel.Nameday);
|
||||||
});
|
});
|
||||||
}); */
|
}); */
|
||||||
return buildCalendar(localEvents, runtimeConfig.public.baseUrl);
|
return buildCalendar(localEvents, baseUrl);
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import localeDescriptions from '~/locale/locales.ts';
|
import localeDescriptions from '~/locale/locales.ts';
|
||||||
import buildLocaleList from '~/src/buildLocaleList.ts';
|
import buildLocaleList from '~/src/buildLocaleList.ts';
|
||||||
|
|
||||||
const getLocaleUrls = (domainBase: string | undefined): Record<string, string> => {
|
export const getLocaleUrls = (domainBase: string | undefined): Record<string, string> => {
|
||||||
if (domainBase) {
|
if (domainBase) {
|
||||||
return Object.fromEntries([
|
return Object.fromEntries([
|
||||||
['_', domainBase.replace('{locale}', '')
|
['_', domainBase.replace('{locale}', '')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user