useyuva 0.0.12 → 0.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +244 -2
- package/dist/esm/chat.js +2 -2
- package/dist/esm/docs.js +4 -4
- package/dist/esm/h3.js +1 -0
- package/dist/esm/{index-c6q8br7d.js → index-9vqd1b2a.js} +1 -1
- package/dist/esm/index-qcd538se.js +2 -0
- package/dist/esm/index-r9f9ttb2.js +2 -0
- package/dist/esm/nitro/module.js +39 -0
- package/dist/esm/nitro/runtime/core.js +64 -0
- package/dist/esm/nitro/runtime/define.js +3 -0
- package/dist/esm/nitro/runtime/identity.js +3 -0
- package/dist/esm/nitro/runtime/plugin.js +3 -0
- package/dist/esm/nitro/runtime/webhook.js +3 -0
- package/dist/esm/nitro/setup.js +65 -0
- package/dist/esm/nuxt/module.js +64 -2
- package/dist/esm/nuxt/runtime/components.js +8 -1
- package/dist/esm/server.js +1 -0
- package/dist/esm/subscribe.js +2 -2
- package/dist/esm/{thread-btm71nxt.js → thread-gx5pssds.js} +1 -1
- package/dist/esm/{yuva-chat-kf9vz8r3.js → yuva-chat-025wzr6w.js} +2 -2
- package/dist/types/h3.d.ts +36 -0
- package/dist/types/nitro/module.d.ts +8 -0
- package/dist/types/nitro/runtime/core.d.ts +41 -0
- package/dist/types/nitro/runtime/define.d.ts +21 -0
- package/dist/types/nitro/setup.d.ts +36 -0
- package/dist/types/nuxt/module.d.ts +17 -3
- package/dist/types/server/analytics.d.ts +52 -0
- package/dist/types/server/encoding.d.ts +6 -0
- package/dist/types/server/identity.d.ts +14 -0
- package/dist/types/server/webhook.d.ts +28 -0
- package/dist/types/server.d.ts +3 -0
- package/dist/types/styles.d.ts +2 -0
- package/dist/yuva-chat.js +6 -6
- package/dist/yuva-docs.js +6 -6
- package/dist/yuva-subscribe.js +2 -2
- package/dist/yuva.js +2 -2
- package/package.json +26 -2
- package/dist/esm/index-98r96a7e.js +0 -2
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createAnalytics,
|
|
3
|
+
signIdentityToken,
|
|
4
|
+
verifyWebhook,
|
|
5
|
+
WebhookVerificationError
|
|
6
|
+
} from "../../server.js";
|
|
7
|
+
const noStore = { "cache-control": "no-store" };
|
|
8
|
+
const notFound = () => new Response(null, { status: 404 });
|
|
9
|
+
export function identityHandler(yuva) {
|
|
10
|
+
return yuva.defineHandler(async (event) => {
|
|
11
|
+
const secret = yuva.config().yuva?.identitySecret;
|
|
12
|
+
if (!secret || !yuva.server.user)
|
|
13
|
+
return notFound();
|
|
14
|
+
const claims = await yuva.server.user(event);
|
|
15
|
+
if (!claims)
|
|
16
|
+
return new Response(null, { status: 401, headers: noStore });
|
|
17
|
+
return Response.json({ token: await signIdentityToken(secret, claims) }, { headers: noStore });
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
export function webhookHandler(yuva) {
|
|
21
|
+
return yuva.defineHandler(async (event) => {
|
|
22
|
+
const secret = yuva.config().yuva?.webhookSecret;
|
|
23
|
+
if (!secret)
|
|
24
|
+
return notFound();
|
|
25
|
+
let payload;
|
|
26
|
+
try {
|
|
27
|
+
payload = await verifyWebhook(secret, yuva.toRequest(event));
|
|
28
|
+
} catch (error) {
|
|
29
|
+
if (error instanceof WebhookVerificationError)
|
|
30
|
+
return new Response(error.message, { status: 401 });
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
const on = yuva.server.webhooks ?? {};
|
|
34
|
+
if (!Object.hasOwn(on, payload.type))
|
|
35
|
+
return new Response(null, { status: 204 });
|
|
36
|
+
const handler = on[payload.type];
|
|
37
|
+
const result = await handler?.(payload, event);
|
|
38
|
+
return result instanceof Response ? result : new Response(null, { status: 204 });
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
export function analyticsPlugin(yuva) {
|
|
42
|
+
return (nitroApp) => {
|
|
43
|
+
const config = yuva.config();
|
|
44
|
+
const { apiKey, propertyId } = config.yuva?.analytics ?? {};
|
|
45
|
+
const server = config.yuva?.server || config.public?.yuva?.analytics?.server || config.public?.yuva?.server;
|
|
46
|
+
if (!apiKey || !propertyId || !server)
|
|
47
|
+
return;
|
|
48
|
+
const analytics = createAnalytics({ server, apiKey, propertyId });
|
|
49
|
+
const tracked = new WeakSet;
|
|
50
|
+
nitroApp.hooks.hook("request", (event) => {
|
|
51
|
+
event.context.yuva = {
|
|
52
|
+
track(e) {
|
|
53
|
+
analytics.track(yuva.trackRequest(event), e);
|
|
54
|
+
tracked.add(event);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
yuva.onResponse(nitroApp.hooks, (event) => {
|
|
59
|
+
if (tracked.has(event))
|
|
60
|
+
yuva.waitUntil(event)?.(analytics.flush());
|
|
61
|
+
});
|
|
62
|
+
nitroApp.hooks.hook("close", () => analytics.close());
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
export const IDENTITY_ROUTE = "/_yuva/identity";
|
|
5
|
+
export const WEBHOOK_ROUTE = "/_yuva/webhook";
|
|
6
|
+
export const SERVER_MODULE = "#yuva/server";
|
|
7
|
+
export function serverRuntimeConfig(current, options) {
|
|
8
|
+
return {
|
|
9
|
+
...current,
|
|
10
|
+
server: current?.server || options.server || "",
|
|
11
|
+
identitySecret: current?.identitySecret || options.identitySecret || "",
|
|
12
|
+
webhookSecret: current?.webhookSecret || options.webhookSecret || "",
|
|
13
|
+
analytics: {
|
|
14
|
+
...current?.analytics,
|
|
15
|
+
apiKey: current?.analytics?.apiKey || options.analytics?.apiKey || "",
|
|
16
|
+
propertyId: current?.analytics?.propertyId || options.analytics?.propertyId || ""
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export function serverParts(config, env, prefix) {
|
|
21
|
+
const set = (value, name) => !!(value || env[`${prefix}YUVA_${name}`]);
|
|
22
|
+
return {
|
|
23
|
+
identity: set(config.identitySecret, "IDENTITY_SECRET"),
|
|
24
|
+
webhook: set(config.webhookSecret, "WEBHOOK_SECRET"),
|
|
25
|
+
analytics: set(config.analytics?.apiKey, "ANALYTICS_API_KEY") && set(config.analytics?.propertyId, "ANALYTICS_PROPERTY_ID")
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export function findServerFile(dir) {
|
|
29
|
+
for (const ext of ["ts", "mts", "js", "mjs"]) {
|
|
30
|
+
const path = join(dir, `yuva.${ext}`);
|
|
31
|
+
if (existsSync(path))
|
|
32
|
+
return path;
|
|
33
|
+
}
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
export function runtimePath(name) {
|
|
37
|
+
return fileURLToPath(new URL(`./runtime/${name}.js`, import.meta.url));
|
|
38
|
+
}
|
|
39
|
+
export function serverModule({ nitro, server, runtimeConfig, h3 = "h3" }) {
|
|
40
|
+
const v3 = nitro >= 3;
|
|
41
|
+
const lines = [
|
|
42
|
+
`import { useRuntimeConfig } from ${JSON.stringify(runtimeConfig)}`,
|
|
43
|
+
...v3 ? [] : [`import { defineEventHandler, getRequestIP, getRequestURL, toWebRequest } from ${JSON.stringify(h3)}`],
|
|
44
|
+
server ? `import server from ${JSON.stringify(server)}` : "const server = {}",
|
|
45
|
+
"export { server }",
|
|
46
|
+
"export const config = () => useRuntimeConfig()",
|
|
47
|
+
...v3 ? [
|
|
48
|
+
"export const defineHandler = (handler) => handler",
|
|
49
|
+
"export const toRequest = (event) => event.req",
|
|
50
|
+
"export const trackRequest = (event) => event.req",
|
|
51
|
+
'export const onResponse = (hooks, fn) => hooks.hook("response", (_response, event) => fn(event))',
|
|
52
|
+
"export const waitUntil = (event) => (event.req.waitUntil ? (promise) => event.waitUntil(promise) : undefined)"
|
|
53
|
+
] : [
|
|
54
|
+
"export const defineHandler = defineEventHandler",
|
|
55
|
+
"export const toRequest = (event) => toWebRequest(event)",
|
|
56
|
+
"export const trackRequest = (event) =>",
|
|
57
|
+
" Object.assign(new Request(getRequestURL(event), { headers: event.headers }), { ip: getRequestIP(event) })",
|
|
58
|
+
'export const onResponse = (hooks, fn) => hooks.hook("afterResponse", (event) => fn(event))',
|
|
59
|
+
"export const waitUntil = (event) => (event.context.waitUntil ? (promise) => event.waitUntil(promise) : undefined)"
|
|
60
|
+
]
|
|
61
|
+
];
|
|
62
|
+
return `${lines.join(`
|
|
63
|
+
`)}
|
|
64
|
+
`;
|
|
65
|
+
}
|
package/dist/esm/nuxt/module.js
CHANGED
|
@@ -1,15 +1,55 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as kit from "@nuxt/kit";
|
|
2
|
+
import {
|
|
3
|
+
addComponent,
|
|
4
|
+
addImports,
|
|
5
|
+
addPlugin,
|
|
6
|
+
addServerHandler,
|
|
7
|
+
addServerImports,
|
|
8
|
+
addServerPlugin,
|
|
9
|
+
addTypeTemplate,
|
|
10
|
+
defineNuxtModule,
|
|
11
|
+
useLogger
|
|
12
|
+
} from "@nuxt/kit";
|
|
13
|
+
import {
|
|
14
|
+
findServerFile,
|
|
15
|
+
IDENTITY_ROUTE,
|
|
16
|
+
runtimePath,
|
|
17
|
+
SERVER_MODULE,
|
|
18
|
+
serverModule,
|
|
19
|
+
serverParts,
|
|
20
|
+
serverRuntimeConfig,
|
|
21
|
+
WEBHOOK_ROUTE
|
|
22
|
+
} from "../nitro/setup.js";
|
|
2
23
|
const components = ["YuvaChat", "YuvaDiscussions", "YuvaPageFeedback", "YuvaSubscribe"];
|
|
24
|
+
const serverTypes = `import type { H3Event } from "h3"
|
|
25
|
+
|
|
26
|
+
declare module "useyuva/nitro/runtime" {
|
|
27
|
+
interface YuvaServerTypes {
|
|
28
|
+
event: H3Event
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export {}
|
|
33
|
+
`;
|
|
3
34
|
export default defineNuxtModule({
|
|
4
35
|
meta: { name: "useyuva", configKey: "yuva" },
|
|
5
36
|
defaults: { server: "", channel: "", locale: "" },
|
|
6
37
|
setup(options, nuxt) {
|
|
38
|
+
const { apiKey, propertyId, ...clientAnalytics } = options.analytics ?? { key: "" };
|
|
39
|
+
const secrets = serverRuntimeConfig(nuxt.options.runtimeConfig.yuva, {
|
|
40
|
+
identitySecret: options.identitySecret,
|
|
41
|
+
webhookSecret: options.webhookSecret,
|
|
42
|
+
analytics: { apiKey, propertyId }
|
|
43
|
+
});
|
|
44
|
+
const parts = serverParts(secrets, process.env, "NUXT_");
|
|
7
45
|
const current = nuxt.options.runtimeConfig.public.yuva ?? {};
|
|
46
|
+
const base = nuxt.options.app.baseURL.replace(/\/+$/, "");
|
|
8
47
|
nuxt.options.runtimeConfig.public.yuva = {
|
|
9
48
|
server: current.server || options.server || "",
|
|
10
49
|
channel: current.channel || options.channel || "",
|
|
11
50
|
locale: current.locale || options.locale || "",
|
|
12
|
-
|
|
51
|
+
identity: current.identity || (parts.identity ? `${base}${IDENTITY_ROUTE}` : ""),
|
|
52
|
+
analytics: current.analytics || (options.analytics ? clientAnalytics : undefined)
|
|
13
53
|
};
|
|
14
54
|
const compilerOptions = nuxt.options.vue.compilerOptions ??= {};
|
|
15
55
|
const isCustomElement = compilerOptions.isCustomElement;
|
|
@@ -20,5 +60,27 @@ export default defineNuxtModule({
|
|
|
20
60
|
addImports({ name: "useYuvaAnalytics", from: "useyuva/nuxt/analytics" });
|
|
21
61
|
if (nuxt.options.runtimeConfig.public.yuva.analytics)
|
|
22
62
|
addPlugin({ src: "useyuva/nuxt/plugin", mode: "client" });
|
|
63
|
+
addServerImports([{ name: "defineYuvaServer", from: "useyuva/nitro/runtime" }]);
|
|
64
|
+
addTypeTemplate({ filename: "types/useyuva-server.d.ts", getContents: () => serverTypes }, { nitro: true });
|
|
65
|
+
if (!parts.identity && !parts.webhook && !parts.analytics)
|
|
66
|
+
return;
|
|
67
|
+
nuxt.options.runtimeConfig.yuva = secrets;
|
|
68
|
+
const server = findServerFile(nuxt.options.serverDir);
|
|
69
|
+
if (!server && parts.identity) {
|
|
70
|
+
useLogger("useyuva").warn(`No yuva.ts in ${nuxt.options.serverDir}, so ${IDENTITY_ROUTE} answers 404`);
|
|
71
|
+
}
|
|
72
|
+
const nitro = kit.getNitroVersion?.(nuxt) ?? 2;
|
|
73
|
+
nuxt.hook("nitro:config", (config) => {
|
|
74
|
+
config.virtual = {
|
|
75
|
+
...config.virtual,
|
|
76
|
+
[SERVER_MODULE]: serverModule({ nitro, server, runtimeConfig: "#imports" })
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
if (parts.identity)
|
|
80
|
+
addServerHandler({ route: IDENTITY_ROUTE, method: "GET", handler: runtimePath("identity") });
|
|
81
|
+
if (parts.webhook)
|
|
82
|
+
addServerHandler({ route: WEBHOOK_ROUTE, method: "POST", handler: runtimePath("webhook") });
|
|
83
|
+
if (parts.analytics)
|
|
84
|
+
addServerPlugin(runtimePath("plugin"));
|
|
23
85
|
}
|
|
24
86
|
});
|
|
@@ -18,12 +18,19 @@ const subscribeProps = {
|
|
|
18
18
|
consent: String,
|
|
19
19
|
privacyUrl: String
|
|
20
20
|
};
|
|
21
|
+
function identityRoute(path) {
|
|
22
|
+
return async () => {
|
|
23
|
+
const response = await fetch(path, { credentials: "same-origin" });
|
|
24
|
+
return response.ok ? (await response.json()).token : null;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
21
27
|
function setup(tag, load, props, attributes, listeners) {
|
|
22
28
|
const config = useRuntimeConfig().public.yuva;
|
|
23
29
|
const element = ref(null);
|
|
30
|
+
const route = config?.identity ? identityRoute(config.identity) : undefined;
|
|
24
31
|
onMounted(() => {
|
|
25
32
|
load();
|
|
26
|
-
watch(() => props.identityToken, (source) => {
|
|
33
|
+
watch(() => props.identityToken === undefined ? route : props.identityToken, (source) => {
|
|
27
34
|
const target = element.value;
|
|
28
35
|
if (!target || typeof source !== "function")
|
|
29
36
|
return;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{DEFAULT_IDENTITY_TTL2,MAX_IDENTITY_TTL2,signIdentityToken2,DEFAULT_WEBHOOK_TOLERANCE2,WebhookVerificationError2,signWebhook2,verifyWebhookBody2,verifyWebhook2}from"./index-qcd538se.js";var MAX_BATCH=100;class AnalyticsEventError extends Error{event;detail;constructor(event,detail){super(`analytics: event ${JSON.stringify(event.name)} refused: ${detail}`);this.name="AnalyticsEventError",this.event=event,this.detail=detail}}class AnalyticsBatchError extends Error{status;body;events;constructor(events,status,body,cause){super(cause===void 0?`analytics: ${events} events not sent: ${status} ${body}`:`analytics: ${events} events not sent: ${cause instanceof Error?cause.message:String(cause)}`,cause===void 0?void 0:{cause});this.name="AnalyticsBatchError",this.status=status,this.body=body,this.events=events}}var QUEUE_FULL="analytics: the queue is full; event dropped",CLOSED="analytics: client closed",rfc3339=(time)=>time.toISOString().replace(/\.?0+Z$/,"Z");function wire(event){return{name:event.name,url:event.url,referrer:event.referrer||void 0,timestamp:rfc3339(event.time),props:event.props&&Object.keys(event.props).length>0?event.props:void 0,revenue:event.revenue?{a:event.revenue.amount,c:event.revenue.currency}:void 0,interactive:event.nonInteractive?!1:void 0,consent:event.consent||void 0,ip:event.ip||void 0,user_agent:event.userAgent||void 0,sec_ch_ua_platform:event.secChUaPlatform||void 0,sec_ch_ua_mobile:event.secChUaMobile||void 0,accept_language:event.acceptLanguage||void 0,visitor_key:event.visitorKey||void 0,persistent_id:event.persistentId||void 0,identity_token:event.identityToken||void 0}}function requestURL(request){let url=new URL(request.url);if(request.headers.get("x-forwarded-proto")?.toLowerCase()==="https")url.protocol="https:";return url.hash="",url.href}var socketIP=(request)=>{let ip=request.ip;return typeof ip==="string"?ip:void 0};function unref(timer){if(typeof timer==="object"&&timer&&"unref"in timer&&typeof timer.unref==="function")timer.unref();else globalThis.Deno?.unrefTimer?.(timer);return timer}var sleep=(ms,hold)=>new Promise((resolve)=>{let timer=setTimeout(resolve,ms);if(!hold)unref(timer)});function createAnalytics(config){if(!config.server||!config.apiKey||!config.propertyId)throw Error("analytics: server, apiKey and propertyId are required");let endpoint=`${config.server.replace(/\/+$/,"")}/v1/analytics/properties/${encodeURIComponent(config.propertyId)}/events`,interval=config.flushInterval&&config.flushInterval>0?config.flushInterval:5000,queueSize=config.queueSize&&config.queueSize>0?config.queueSize:1e4,maxRetries=config.maxRetries||5,minBackoff=config.minBackoff&&config.minBackoff>0?config.minBackoff:1000,clientIP=config.clientIP??socketIP,queue=[],closed=!1,timer,chain=Promise.resolve(),report=(error)=>{try{config.onError?.(error)}catch{}};async function post(body){let res=await(config.fetch??fetch)(endpoint,{method:"POST",headers:{Authorization:`Bearer ${config.apiKey}`,"Content-Type":"application/json"},body}),raw=(await res.text()).slice(0,65536).trim(),seconds=Number(res.headers.get("retry-after"));return{status:res.status,raw,retryAfter:Number.isInteger(seconds)&&seconds>0?seconds*1000:0}}async function sendBatch(batch,hold){let body=JSON.stringify({events:batch.map(wire)}),backoff=minBackoff;for(let attempt=0;;attempt++){let res=await post(body).catch((error)=>({error}));if(!("error"in res)){if(res.status===202){try{let result=JSON.parse(res.raw);for(let{index,detail}of result.errors??[]){let event=batch[index];if(event)report(new AnalyticsEventError(event,detail))}}catch{}return}if(res.status!==429&&res.status<500)return new AnalyticsBatchError(batch.length,res.status,res.raw)}if(attempt>=maxRetries)return"error"in res?new AnalyticsBatchError(batch.length,0,"",res.error):new AnalyticsBatchError(batch.length,res.status,res.raw);await sleep(Math.max(backoff,"error"in res?0:res.retryAfter),hold),backoff=Math.min(backoff*2,60000)}}async function sendAll(hold){let last;for(;;){let batch=queue.slice(0,100);if(queue=queue.slice(batch.length),batch.length===0)return last;let error=await sendBatch(batch,hold);if(error)last=error,report(error)}}let run=(hold)=>{let next=chain.then(()=>sendAll(hold));return chain=next,next};function send(event){if(!event.name||!event.url)throw Error("analytics: an event needs a name and a url");if(closed)throw Error(CLOSED);if(queue.length>=queueSize){report(Error(QUEUE_FULL));return}if(queue.push({...event,time:event.time??new Date}),queue.length>=100)run(!1);else if(!timer)timer=unref(setTimeout(()=>{timer=void 0,run(!1)},interval))}function track(request,event){let headers=request.headers;if(headers.get("dnt")==="1"||headers.get("sec-gpc")==="1")return;let e={...event};if(!e.visitorKey){if(!e.ip)e.ip=clientIP(request)??void 0;if(!e.userAgent)e.userAgent=headers.get("user-agent")??void 0,e.secChUaPlatform=headers.get("sec-ch-ua-platform")??void 0,e.secChUaMobile=headers.get("sec-ch-ua-mobile")??void 0}if(!e.acceptLanguage)e.acceptLanguage=headers.get("accept-language")??void 0;if(!e.url)e.url=requestURL(request);if(!e.referrer)e.referrer=headers.get("referer")??void 0;send(e)}return{track,send,flush:()=>run(!0),async close(){if(closed)return;if(closed=!0,timer)clearTimeout(timer);return timer=void 0,run(!0)}}}export{AnalyticsBatchError,AnalyticsEventError,DEFAULT_IDENTITY_TTL2 as DEFAULT_IDENTITY_TTL,DEFAULT_WEBHOOK_TOLERANCE2 as DEFAULT_WEBHOOK_TOLERANCE,MAX_BATCH,MAX_IDENTITY_TTL2 as MAX_IDENTITY_TTL,WebhookVerificationError2 as WebhookVerificationError,createAnalytics,signIdentityToken2 as signIdentityToken,signWebhook2 as signWebhook,verifyWebhook2 as verifyWebhook,verifyWebhookBody2 as verifyWebhookBody};
|
package/dist/esm/subscribe.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{el}from"./index-rdzxvj2r.js";import{ApiError2,call,mailingLists,createSubscription}from"./index-gk84nm8f.js";import{translate,localeIn,directionOf,contrastOn}from"./index-
|
|
1
|
+
import{el}from"./index-rdzxvj2r.js";import{ApiError2,call,mailingLists,createSubscription}from"./index-gk84nm8f.js";import{translate,localeIn,directionOf,setStyles,contrastOn}from"./index-r9f9ttb2.js";var messages=JSON.parse('{"-g5O6h":["Choose at least one list."],"1w51t9":["Subscribing…"],"EDl9kS":["Subscribe"],"E_LjOR":["Enter your name."],"E_qvzP":["Enter a valid e-mail address."],"GQVIIl":["You seem to be offline."],"ScJ9fj":["Privacy policy"],"XJURKP":["E-mail address"],"YnOaHp":["Your name (optional)"],"dMJfG5":["I want to receive e-mails about ",["list"]," from ",["inbox"],". I can unsubscribe at any time."],"eku1-t":["Your account has no e-mail address yet."],"h16FyT":["Lists"],"jWgNnM":["Could not subscribe. Try again."],"lDEbTy":["Tick the box to agree."],"q8yluz":["Your name"],"rgySXy":["Thanks! You are subscribed."],"tzsBOP":["Too many attempts. Wait a moment and try again."],"x6dU53":["Check your inbox to confirm."],"y3k2zM":["Almost done. Check your inbox and confirm your subscription."]}');var messages2=JSON.parse('{"-g5O6h":["Wählen Sie mindestens eine Liste."],"1w51t9":["Wird angemeldet…"],"EDl9kS":["Abonnieren"],"E_LjOR":["Geben Sie Ihren Namen ein."],"E_qvzP":["Geben Sie eine gültige E-Mail-Adresse ein."],"GQVIIl":["Sie scheinen offline zu sein."],"ScJ9fj":["Datenschutzerklärung"],"XJURKP":["E-Mail-Adresse"],"YnOaHp":["Ihr Name (optional)"],"dMJfG5":["Ich möchte E-Mails von ",["inbox"]," zu ",["list"]," erhalten. Ich kann mich jederzeit abmelden."],"eku1-t":["Ihr Konto hat noch keine E-Mail-Adresse."],"h16FyT":["Listen"],"jWgNnM":["Anmeldung fehlgeschlagen. Versuchen Sie es erneut."],"lDEbTy":["Setzen Sie das Häkchen, um zuzustimmen."],"q8yluz":["Ihr Name"],"rgySXy":["Danke! Sie sind angemeldet."],"tzsBOP":["Zu viele Versuche. Warten Sie einen Moment und versuchen Sie es erneut."],"x6dU53":["Sehen Sie zur Bestätigung in Ihr Postfach."],"y3k2zM":["Fast geschafft. Sehen Sie in Ihr Postfach und bestätigen Sie Ihr Abonnement."]}');var messages3=JSON.parse('{"-g5O6h":["En az bir liste seçin."],"1w51t9":["Abone olunuyor…"],"EDl9kS":["Abone ol"],"E_LjOR":["Adınızı girin."],"E_qvzP":["Geçerli bir e-posta adresi girin."],"GQVIIl":["Çevrimdışı görünüyorsunuz."],"ScJ9fj":["Gizlilik politikası"],"XJURKP":["E-posta adresi"],"YnOaHp":["Adınız (isteğe bağlı)"],"dMJfG5":[["list"]," hakkında ",["inbox"]," tarafından gönderilen e-postaları almak istiyorum. Aboneliğimi istediğim zaman bırakabilirim."],"eku1-t":["Hesabınızda henüz bir e-posta adresi yok."],"h16FyT":["Listeler"],"jWgNnM":["Abone olunamadı. Yeniden deneyin."],"lDEbTy":["Onaylamak için kutuyu işaretleyin."],"q8yluz":["Adınız"],"rgySXy":["Teşekkürler! Abone oldunuz."],"tzsBOP":["Çok fazla deneme. Biraz bekleyip tekrar deneyin."],"x6dU53":["Onaylamak için gelen kutunuza bakın."],"y3k2zM":["Neredeyse bitti. Gelen kutunuza bakın ve aboneliğinizi onaylayın."]}');var catalogs={en:messages,tr:messages3,de:messages2},tokenMinimumAge=2100,fetcher=(url,init)=>fetch(url,init),Base=typeof HTMLElement>"u"?class{}:HTMLElement,scriptSrc=typeof document<"u"&&document.currentScript instanceof HTMLScriptElement?document.currentScript.src:"",styles=`
|
|
2
2
|
:host{display:block;line-height:1.5}
|
|
3
3
|
:host([hidden]),[hidden]{display:none!important}
|
|
4
4
|
*{box-sizing:border-box}
|
|
@@ -30,4 +30,4 @@ legend{padding:0;margin-block-end:4px;font-weight:600}
|
|
|
30
30
|
.error{color:var(--d)}
|
|
31
31
|
.trap{position:absolute;inset-inline-start:-1e4px;inline-size:1px;overflow:hidden}
|
|
32
32
|
@media (max-width:480px){input{font-size:16px}}
|
|
33
|
-
`;class YuvaSubscribeElement extends Base{static observedAttributes=["channel","server","locale","dir","lists","layout","name","button-text","consent","privacy-url","identity-token"];static loadClient=null;#root;#messages=messages;#connected=!1;#generation=0;#phase="loading";#refused=!1;#inbox=null;#offered=[];#chosen=new Set;#token="";#tokenAt=0;#confirmation=!1;#error="";#emailError="";#nameError="";#consentError="";#identity=null;#client=null;#busy=new Set;#email=el("input");#name=el("input");#trap=el("input");#consent=el("input");#status=el("p");constructor(){super();this.#root=this.attachShadow({mode:"open"}),this.#email.type="email",this.#email.autocomplete="email",this.#email.required=!0,this.#email.maxLength=320,this.#email.id="email",this.#name.autocomplete="name",this.#name.maxLength=200,this.#name.id="name",this.#trap.name="website",this.#trap.tabIndex=-1,this.#trap.autocomplete="off",this.#consent.type="checkbox",this.#consent.id="consent",this.#consent.addEventListener("change",()=>{this.#consentError="",this.#render()});for(let input of[this.#email,this.#name])input.setAttribute("part","field"),input.dir="auto";this.#status.setAttribute("part","status"),this.#status.setAttribute("role","status"),this.#status.setAttribute("aria-live","polite")}get channel(){return this.getAttribute("channel")}set channel(value){this.#attribute("channel",value)}get server(){return(this.getAttribute("server")||(scriptSrc?new URL(scriptSrc).origin:location.origin)).replace(/\/+$/,"")}set server(value){this.#attribute("server",value)}get locale(){return localeIn(catalogs,[this.getAttribute("locale"),navigator.language])}set locale(value){this.#attribute("locale",value)}get lists(){return this.#offered.map((item)=>item.list)}setIdentityToken(source){if(this.#identity=source,this.#connected)this.#load()}connectedCallback(){this.#connected=!0,this.#load()}disconnectedCallback(){this.#connected=!1}attributeChangedCallback(name,previous,value){if(!this.#connected||previous===value)return;if(["channel","server","lists","identity-token"].includes(name))return void this.#load();this.#render()}#attribute(name,value){if(value===null||value===void 0||value==="")this.removeAttribute(name);else this.setAttribute(name,value)}#t(descriptor){return translate(this.#messages,descriptor,messages)}get#identified(){return!!this.#identity||this.hasAttribute("identity-token")}async#identityToken(){return this.#identity?await this.#identity()??null:this.getAttribute("identity-token")}#wanted(lists){let ids=(this.getAttribute("lists")??"").split(",").map((id)=>id.trim()).filter((id)=>id&&id!=="all");if(ids.length===0)return lists;let found=ids.map((id)=>lists.find((list)=>list.id===id)).filter((list)=>!!list);if(found.length<ids.length)console.warn(`Yuva: some lists in "${ids.join(",")}" are not public lists`);return found}async#load(){let generation=++this.#generation,channel=this.channel;if(this.#refused=!1,this.#phase="loading",this.#offered=[],this.#error="",this.#client=null,this.#render(),!channel)return;let server=this.server;try{let inbox=call(fetcher,server,`/client/v1/channels/${encodeURIComponent(channel)}`),offered=null;if(this.#identified&&YuvaSubscribeElement.loadClient&&await this.#identityToken()){let{createYuvaClient}=await YuvaSubscribeElement.loadClient(),client=createYuvaClient({server,channel,identityToken:()=>this.#identityToken()});try{let{items}=await client.subscriptions(),wanted=new Set(this.#wanted(items.map((item)=>item.list)));offered=items.filter((item)=>wanted.has(item.list)),this.#client=client}catch(error){if(!(error instanceof ApiError2)||error.code!=="identity_required")throw error}}if(!offered){let{lists,form_token}=await mailingLists(fetcher,server,channel);offered=this.#wanted(lists).map((list)=>({list})),this.#token=form_token,this.#tokenAt=Date.now()}if(this.#inbox=await inbox,generation!==this.#generation)return;if(this.#offered=offered,this.#chosen=new Set(offered.length===1?[offered[0].list.id]:[]),this.#phase="idle",offered.length===0)console.warn(`Yuva: channel ${channel} has no public mailing lists to offer`)}catch(error){if(generation!==this.#generation)return;if(this.#refusal(error))return;this.#phase="idle",this.#error=this.#errorText(error)}this.#render()}#refusal(error){let refused=error instanceof ApiError2&&(error.status===404||error.code==="origin_not_allowed"||error.code==="page_origin");if(refused)this.#refused=!0,console.warn(`Yuva: channel ${this.channel} is unknown, offers no such list or does not allow ${location.origin}`),this.#render();return refused}#errorText(error){let code=error instanceof ApiError2?error.code:"";if(code==="rate_limited")return this.#t({id:"tzsBOP"});if(code==="network")return this.#t({id:"GQVIIl"});if(code==="no_email")return this.#t({id:"eku1-t"});return this.#t({id:"jWgNnM"})}#emit(type,detail){this.dispatchEvent(new CustomEvent(type,{detail,bubbles:!0,composed:!0}))}#failed(error){this.#emit("yuva-subscribe-error",{code:error instanceof ApiError2?error.code:"error"})}consentText(lists=this.#selected()){let custom=this.getAttribute("consent")?.trim();if(custom)return custom;let names=(lists.length?lists:this.lists).map((list)=>list.name),list=new Intl.ListFormat(this.locale,{type:"conjunction"}).format(names),inbox=this.#inbox?.name??"";return this.#t({id:"dMJfG5",values:{list,inbox}})}#selected(){return this.lists.filter((list)=>this.#chosen.has(list.id))}async#submit(){if(this.#phase!=="idle"||!this.channel)return;let lists=this.#selected(),email=this.#email.value.trim(),name=this.#name.value.trim(),asksName=this.getAttribute("name");if(this.#error=lists.length===0?this.#t({id:"-g5O6h"}):"",this.#emailError=this.#email.checkValidity()&&email?"":this.#t({id:"E_qvzP"}),this.#nameError=asksName==="required"&&!name?this.#t({id:"E_LjOR"}):"",this.#consentError=this.#consent.checked?"":this.#t({id:"lDEbTy"}),this.#error||this.#emailError||this.#nameError||this.#consentError){this.#render();let invalid=[this.#emailError&&this.#email,this.#nameError&&this.#name,this.#consentError&&this.#consent];for(let input of invalid)if(input)return input.focus();return}let channel=this.channel,generation=this.#generation,consent_text=this.consentText(lists);this.#phase="submitting",this.#render();let send=async(retry)=>{let wait=this.#tokenAt+tokenMinimumAge-Date.now();if(wait>0)await new Promise((resolve)=>setTimeout(resolve,wait));try{let{confirmation}=await createSubscription(fetcher,this.server,channel,{email,name:asksName==="optional"||asksName==="required"?name||void 0:void 0,list_ids:lists.map((list)=>list.id),locale:this.locale,page_url:location.href.split("#")[0].slice(0,2000),consent_text,form_token:this.#token,website:this.#trap.value||void 0});return this.#confirmation=confirmation,!0}catch(error){if(retry&&error instanceof ApiError2&&error.code==="form_token"){let fresh=await mailingLists(fetcher,this.server,channel);return this.#token=fresh.form_token,this.#tokenAt=Date.now(),send(!1)}throw error}};try{await send(!0)}catch(error){if(generation!==this.#generation)return;if(this.#failed(error),this.#phase="idle",this.#refusal(error))return;if(error instanceof ApiError2&&error.code==="invalid_email")return this.#emailError=this.#t({id:"E_qvzP"}),this.#render(),this.#email.focus();return this.#error=this.#errorText(error),this.#render()}if(generation!==this.#generation)return;this.#phase="done",this.#emit("yuva-subscribe",{lists:lists.map((list)=>list.id),confirmation:this.#confirmation}),this.#render()}async#toggle(item,on){let client=this.#client;if(!client||this.#busy.has(item.list.id))return;this.#busy.add(item.list.id),this.#error="",this.#render();try{if(on){let{state}=await client.subscribeList(item.list.id,{consent_text:this.consentText([item.list]),page_url:location.href.split("#")[0].slice(0,2000)});item.state=state,this.#emit("yuva-subscribe",{lists:[item.list.id],confirmation:state==="pending"})}else await client.unsubscribeList(item.list.id),item.state="unsubscribed"}catch(error){this.#failed(error),this.#error=this.#errorText(error)}if(this.#busy.delete(item.list.id),client===this.#client)this.#render()}#errorFor(input,text){if(input.setAttribute("aria-invalid",String(!!text)),!text)return input.removeAttribute("aria-describedby"),null;let id=`${input.id}-error`;input.setAttribute("aria-describedby",id);let error=el("p","error",text);return error.id=id,error}#check(text,checked,onChange,key){let label=el("label","check"),box=el("input");box.type="checkbox",box.checked=checked,box.dataset.key=key,box.addEventListener("change",()=>onChange(box.checked));let body=el("span","text");return body.append(...text),label.append(box,body),label}#lists(identity){if(!identity&&this.#offered.length<2)return null;let group=el("fieldset");group.append(el("legend","",this.#t({id:"h16FyT"})));for(let item of this.#offered){let text=[el("span","",item.list.name)];if(item.list.description)text.push(el("span","muted",item.list.description));if(identity){if(text.push(el("span","muted consent",this.consentText([item.list]))),item.state==="pending")text.push(el("span","muted",this.#t({id:"x6dU53"})))}let on=identity?item.state==="subscribed"||item.state==="pending":this.#chosen.has(item.list.id),label=this.#check(text,on,(checked)=>{if(identity)return void this.#toggle(item,checked);if(checked)this.#chosen.add(item.list.id);else this.#chosen.delete(item.list.id);this.#error="",this.#render()},item.list.id),box=label.querySelector("input");if(identity)box.setAttribute("role","switch"),box.setAttribute("aria-checked",String(box.checked)),box.addEventListener("keydown",(event)=>{if(event.key!=="Enter")return;event.preventDefault(),box.click()}),box.disabled=this.#busy.has(item.list.id);else box.disabled=this.#phase==="submitting";group.append(label)}return group}#form(){let form=el("form",this.getAttribute("layout")==="inline"?"inline":"");form.noValidate=!0,form.addEventListener("submit",(event)=>{event.preventDefault(),this.#submit()});let busy=this.#phase==="submitting",lists=this.#lists(!1);if(lists)form.append(lists);let row=el("div","row"),errors=[],asksName=this.getAttribute("name");if(asksName==="optional"||asksName==="required"){this.#name.placeholder=asksName==="required"?this.#t({id:"q8yluz"}):this.#t({id:"YnOaHp"}),this.#name.setAttribute("aria-label",this.#name.placeholder),this.#name.required=asksName==="required",this.#name.disabled=busy,row.append(this.#name);let error=this.#errorFor(this.#name,this.#nameError);if(error)errors.push(error)}this.#email.placeholder=this.#t({id:"XJURKP"}),this.#email.setAttribute("aria-label",this.#email.placeholder),this.#email.disabled=busy,row.append(this.#email);let emailError=this.#errorFor(this.#email,this.#emailError);if(emailError)errors.push(emailError);let button=el("button","",busy?this.#t({id:"1w51t9"}):this.getAttribute("button-text")||this.#t({id:"EDl9kS"}));button.type="submit",button.disabled=busy,button.setAttribute("part","button"),row.append(button);let trap=el("div","trap");trap.setAttribute("aria-hidden","true"),trap.append(this.#trap);let consentText=el("span","",this.consentText()),consent=el("label","check consent");consent.setAttribute("part","consent"),this.#consent.disabled=busy;let body=el("span");body.append(consentText);let privacy=this.getAttribute("privacy-url");if(privacy&&/^https?:\/\//i.test(privacy)){let link=el("a","",this.#t({id:"ScJ9fj"}));link.href=privacy,link.target="_blank",link.rel="noopener noreferrer",body.append(" ",link)}consent.append(this.#consent,body);let consentError=this.#errorFor(this.#consent,this.#consentError);if(form.append(row,...errors,consent),consentError)form.append(consentError);return form.append(trap),form}#render(){if(this.#refused||!this.channel||this.#phase!=="loading"&&this.#offered.length===0&&!this.#error){this.#root.replaceChildren();return}let locale=this.locale;this.#messages=catalogs[locale]??messages;let dir=this.getAttribute("dir"),wrapper=el("div","frame");wrapper.dir=dir==="rtl"||dir==="ltr"?dir:directionOf(locale),wrapper.lang=locale;let brand=this.#inbox?.chat.launcher_color??this.#inbox?.branding.color;if(brand&&/^#[0-9a-f]{6}$/i.test(brand))wrapper.style.setProperty("--brand",brand),wrapper.style.setProperty("--brand-on",contrastOn(brand));let status="";if(this.#phase==="done")status=this.#confirmation?this.#t({id:"y3k2zM"}):this.#t({id:"rgySXy"});if(this.#status.textContent=status,this.#phase==="idle"||this.#phase==="submitting"){let content=this.#client?this.#lists(!0):this.#form();if(content)wrapper.append(content)}if(wrapper.append(this.#status),this.#error){let error=el("p","error",this.#error);error.setAttribute("role","alert"),wrapper.append(error)}let focusedKey,focused=null;try{focused=this.#root.activeElement}catch{}if(focused instanceof HTMLInputElement)focusedKey=focused.dataset.key;let style=el("style");style.textContent=styles,this.#root.replaceChildren(style,wrapper);let again=focusedKey?this.#root.querySelector(`[data-key="${focusedKey}"]`):focused;if(again instanceof HTMLElement&&again.isConnected)again.focus({preventScroll:!0})}}function defineSubscribe(){if(typeof customElements>"u")return;if(!customElements.get("yuva-subscribe"))customElements.define("yuva-subscribe",YuvaSubscribeElement)}YuvaSubscribeElement.loadClient=()=>import("./client-ebw9d6ms.js");defineSubscribe();export{YuvaSubscribeElement,defineSubscribe};
|
|
33
|
+
`;class YuvaSubscribeElement extends Base{static observedAttributes=["channel","server","locale","dir","lists","layout","name","button-text","consent","privacy-url","identity-token"];static loadClient=null;#root;#messages=messages;#connected=!1;#generation=0;#phase="loading";#refused=!1;#inbox=null;#offered=[];#chosen=new Set;#token="";#tokenAt=0;#confirmation=!1;#error="";#emailError="";#nameError="";#consentError="";#identity=null;#client=null;#busy=new Set;#email=el("input");#name=el("input");#trap=el("input");#consent=el("input");#status=el("p");constructor(){super();this.#root=this.attachShadow({mode:"open"}),this.#email.type="email",this.#email.autocomplete="email",this.#email.required=!0,this.#email.maxLength=320,this.#email.id="email",this.#name.autocomplete="name",this.#name.maxLength=200,this.#name.id="name",this.#trap.name="website",this.#trap.tabIndex=-1,this.#trap.autocomplete="off",this.#consent.type="checkbox",this.#consent.id="consent",this.#consent.addEventListener("change",()=>{this.#consentError="",this.#render()});for(let input of[this.#email,this.#name])input.setAttribute("part","field"),input.dir="auto";this.#status.setAttribute("part","status"),this.#status.setAttribute("role","status"),this.#status.setAttribute("aria-live","polite")}get channel(){return this.getAttribute("channel")}set channel(value){this.#attribute("channel",value)}get server(){return(this.getAttribute("server")||(scriptSrc?new URL(scriptSrc).origin:location.origin)).replace(/\/+$/,"")}set server(value){this.#attribute("server",value)}get locale(){return localeIn(catalogs,[this.getAttribute("locale"),navigator.language])}set locale(value){this.#attribute("locale",value)}get lists(){return this.#offered.map((item)=>item.list)}setIdentityToken(source){if(this.#identity=source,this.#connected)this.#load()}connectedCallback(){this.#connected=!0,this.#load()}disconnectedCallback(){this.#connected=!1}attributeChangedCallback(name,previous,value){if(!this.#connected||previous===value)return;if(["channel","server","lists","identity-token"].includes(name))return void this.#load();this.#render()}#attribute(name,value){if(value===null||value===void 0||value==="")this.removeAttribute(name);else this.setAttribute(name,value)}#t(descriptor){return translate(this.#messages,descriptor,messages)}get#identified(){return!!this.#identity||this.hasAttribute("identity-token")}async#identityToken(){return this.#identity?await this.#identity()??null:this.getAttribute("identity-token")}#wanted(lists){let ids=(this.getAttribute("lists")??"").split(",").map((id)=>id.trim()).filter((id)=>id&&id!=="all");if(ids.length===0)return lists;let found=ids.map((id)=>lists.find((list)=>list.id===id)).filter((list)=>!!list);if(found.length<ids.length)console.warn(`Yuva: some lists in "${ids.join(",")}" are not public lists`);return found}async#load(){let generation=++this.#generation,channel=this.channel;if(this.#refused=!1,this.#phase="loading",this.#offered=[],this.#error="",this.#client=null,this.#render(),!channel)return;let server=this.server;try{let inbox=call(fetcher,server,`/client/v1/channels/${encodeURIComponent(channel)}`),offered=null;if(this.#identified&&YuvaSubscribeElement.loadClient&&await this.#identityToken()){let{createYuvaClient}=await YuvaSubscribeElement.loadClient(),client=createYuvaClient({server,channel,identityToken:()=>this.#identityToken()});try{let{items}=await client.subscriptions(),wanted=new Set(this.#wanted(items.map((item)=>item.list)));offered=items.filter((item)=>wanted.has(item.list)),this.#client=client}catch(error){if(!(error instanceof ApiError2)||error.code!=="identity_required")throw error}}if(!offered){let{lists,form_token}=await mailingLists(fetcher,server,channel);offered=this.#wanted(lists).map((list)=>({list})),this.#token=form_token,this.#tokenAt=Date.now()}if(this.#inbox=await inbox,generation!==this.#generation)return;if(this.#offered=offered,this.#chosen=new Set(offered.length===1?[offered[0].list.id]:[]),this.#phase="idle",offered.length===0)console.warn(`Yuva: channel ${channel} has no public mailing lists to offer`)}catch(error){if(generation!==this.#generation)return;if(this.#refusal(error))return;this.#phase="idle",this.#error=this.#errorText(error)}this.#render()}#refusal(error){let refused=error instanceof ApiError2&&(error.status===404||error.code==="origin_not_allowed"||error.code==="page_origin");if(refused)this.#refused=!0,console.warn(`Yuva: channel ${this.channel} is unknown, offers no such list or does not allow ${location.origin}`),this.#render();return refused}#errorText(error){let code=error instanceof ApiError2?error.code:"";if(code==="rate_limited")return this.#t({id:"tzsBOP"});if(code==="network")return this.#t({id:"GQVIIl"});if(code==="no_email")return this.#t({id:"eku1-t"});return this.#t({id:"jWgNnM"})}#emit(type,detail){this.dispatchEvent(new CustomEvent(type,{detail,bubbles:!0,composed:!0}))}#failed(error){this.#emit("yuva-subscribe-error",{code:error instanceof ApiError2?error.code:"error"})}consentText(lists=this.#selected()){let custom=this.getAttribute("consent")?.trim();if(custom)return custom;let names=(lists.length?lists:this.lists).map((list)=>list.name),list=new Intl.ListFormat(this.locale,{type:"conjunction"}).format(names),inbox=this.#inbox?.name??"";return this.#t({id:"dMJfG5",values:{list,inbox}})}#selected(){return this.lists.filter((list)=>this.#chosen.has(list.id))}async#submit(){if(this.#phase!=="idle"||!this.channel)return;let lists=this.#selected(),email=this.#email.value.trim(),name=this.#name.value.trim(),asksName=this.getAttribute("name");if(this.#error=lists.length===0?this.#t({id:"-g5O6h"}):"",this.#emailError=this.#email.checkValidity()&&email?"":this.#t({id:"E_qvzP"}),this.#nameError=asksName==="required"&&!name?this.#t({id:"E_LjOR"}):"",this.#consentError=this.#consent.checked?"":this.#t({id:"lDEbTy"}),this.#error||this.#emailError||this.#nameError||this.#consentError){this.#render();let invalid=[this.#emailError&&this.#email,this.#nameError&&this.#name,this.#consentError&&this.#consent];for(let input of invalid)if(input)return input.focus();return}let channel=this.channel,generation=this.#generation,consent_text=this.consentText(lists);this.#phase="submitting",this.#render();let send=async(retry)=>{let wait=this.#tokenAt+tokenMinimumAge-Date.now();if(wait>0)await new Promise((resolve)=>setTimeout(resolve,wait));try{let{confirmation}=await createSubscription(fetcher,this.server,channel,{email,name:asksName==="optional"||asksName==="required"?name||void 0:void 0,list_ids:lists.map((list)=>list.id),locale:this.locale,page_url:location.href.split("#")[0].slice(0,2000),consent_text,form_token:this.#token,website:this.#trap.value||void 0});return this.#confirmation=confirmation,!0}catch(error){if(retry&&error instanceof ApiError2&&error.code==="form_token"){let fresh=await mailingLists(fetcher,this.server,channel);return this.#token=fresh.form_token,this.#tokenAt=Date.now(),send(!1)}throw error}};try{await send(!0)}catch(error){if(generation!==this.#generation)return;if(this.#failed(error),this.#phase="idle",this.#refusal(error))return;if(error instanceof ApiError2&&error.code==="invalid_email")return this.#emailError=this.#t({id:"E_qvzP"}),this.#render(),this.#email.focus();return this.#error=this.#errorText(error),this.#render()}if(generation!==this.#generation)return;this.#phase="done",this.#emit("yuva-subscribe",{lists:lists.map((list)=>list.id),confirmation:this.#confirmation}),this.#render()}async#toggle(item,on){let client=this.#client;if(!client||this.#busy.has(item.list.id))return;this.#busy.add(item.list.id),this.#error="",this.#render();try{if(on){let{state}=await client.subscribeList(item.list.id,{consent_text:this.consentText([item.list]),page_url:location.href.split("#")[0].slice(0,2000)});item.state=state,this.#emit("yuva-subscribe",{lists:[item.list.id],confirmation:state==="pending"})}else await client.unsubscribeList(item.list.id),item.state="unsubscribed"}catch(error){this.#failed(error),this.#error=this.#errorText(error)}if(this.#busy.delete(item.list.id),client===this.#client)this.#render()}#errorFor(input,text){if(input.setAttribute("aria-invalid",String(!!text)),!text)return input.removeAttribute("aria-describedby"),null;let id=`${input.id}-error`;input.setAttribute("aria-describedby",id);let error=el("p","error",text);return error.id=id,error}#check(text,checked,onChange,key){let label=el("label","check"),box=el("input");box.type="checkbox",box.checked=checked,box.dataset.key=key,box.addEventListener("change",()=>onChange(box.checked));let body=el("span","text");return body.append(...text),label.append(box,body),label}#lists(identity){if(!identity&&this.#offered.length<2)return null;let group=el("fieldset");group.append(el("legend","",this.#t({id:"h16FyT"})));for(let item of this.#offered){let text=[el("span","",item.list.name)];if(item.list.description)text.push(el("span","muted",item.list.description));if(identity){if(text.push(el("span","muted consent",this.consentText([item.list]))),item.state==="pending")text.push(el("span","muted",this.#t({id:"x6dU53"})))}let on=identity?item.state==="subscribed"||item.state==="pending":this.#chosen.has(item.list.id),label=this.#check(text,on,(checked)=>{if(identity)return void this.#toggle(item,checked);if(checked)this.#chosen.add(item.list.id);else this.#chosen.delete(item.list.id);this.#error="",this.#render()},item.list.id),box=label.querySelector("input");if(identity)box.setAttribute("role","switch"),box.setAttribute("aria-checked",String(box.checked)),box.addEventListener("keydown",(event)=>{if(event.key!=="Enter")return;event.preventDefault(),box.click()}),box.disabled=this.#busy.has(item.list.id);else box.disabled=this.#phase==="submitting";group.append(label)}return group}#form(){let form=el("form",this.getAttribute("layout")==="inline"?"inline":"");form.noValidate=!0,form.addEventListener("submit",(event)=>{event.preventDefault(),this.#submit()});let busy=this.#phase==="submitting",lists=this.#lists(!1);if(lists)form.append(lists);let row=el("div","row"),errors=[],asksName=this.getAttribute("name");if(asksName==="optional"||asksName==="required"){this.#name.placeholder=asksName==="required"?this.#t({id:"q8yluz"}):this.#t({id:"YnOaHp"}),this.#name.setAttribute("aria-label",this.#name.placeholder),this.#name.required=asksName==="required",this.#name.disabled=busy,row.append(this.#name);let error=this.#errorFor(this.#name,this.#nameError);if(error)errors.push(error)}this.#email.placeholder=this.#t({id:"XJURKP"}),this.#email.setAttribute("aria-label",this.#email.placeholder),this.#email.disabled=busy,row.append(this.#email);let emailError=this.#errorFor(this.#email,this.#emailError);if(emailError)errors.push(emailError);let button=el("button","",busy?this.#t({id:"1w51t9"}):this.getAttribute("button-text")||this.#t({id:"EDl9kS"}));button.type="submit",button.disabled=busy,button.setAttribute("part","button"),row.append(button);let trap=el("div","trap");trap.setAttribute("aria-hidden","true"),trap.append(this.#trap);let consentText=el("span","",this.consentText()),consent=el("label","check consent");consent.setAttribute("part","consent"),this.#consent.disabled=busy;let body=el("span");body.append(consentText);let privacy=this.getAttribute("privacy-url");if(privacy&&/^https?:\/\//i.test(privacy)){let link=el("a","",this.#t({id:"ScJ9fj"}));link.href=privacy,link.target="_blank",link.rel="noopener noreferrer",body.append(" ",link)}consent.append(this.#consent,body);let consentError=this.#errorFor(this.#consent,this.#consentError);if(form.append(row,...errors,consent),consentError)form.append(consentError);return form.append(trap),form}#render(){if(this.#refused||!this.channel||this.#phase!=="loading"&&this.#offered.length===0&&!this.#error){this.#root.replaceChildren();return}let locale=this.locale;this.#messages=catalogs[locale]??messages;let dir=this.getAttribute("dir"),wrapper=el("div","frame");wrapper.dir=dir==="rtl"||dir==="ltr"?dir:directionOf(locale),wrapper.lang=locale;let brand=this.#inbox?.chat.launcher_color??this.#inbox?.branding.color;if(brand&&/^#[0-9a-f]{6}$/i.test(brand))wrapper.style.setProperty("--brand",brand),wrapper.style.setProperty("--brand-on",contrastOn(brand));let status="";if(this.#phase==="done")status=this.#confirmation?this.#t({id:"y3k2zM"}):this.#t({id:"rgySXy"});if(this.#status.textContent=status,this.#phase==="idle"||this.#phase==="submitting"){let content=this.#client?this.#lists(!0):this.#form();if(content)wrapper.append(content)}if(wrapper.append(this.#status),this.#error){let error=el("p","error",this.#error);error.setAttribute("role","alert"),wrapper.append(error)}let focusedKey,focused=null;try{focused=this.#root.activeElement}catch{}if(focused instanceof HTMLInputElement)focusedKey=focused.dataset.key;let fallback=setStyles(this.#root,styles);this.#root.replaceChildren(...fallback?[fallback]:[],wrapper);let again=focusedKey?this.#root.querySelector(`[data-key="${focusedKey}"]`):focused;if(again instanceof HTMLElement&&again.isConnected)again.focus({preventScroll:!0})}}function defineSubscribe(){if(typeof customElements>"u")return;if(!customElements.get("yuva-subscribe"))customElements.define("yuva-subscribe",YuvaSubscribeElement)}YuvaSubscribeElement.loadClient=()=>import("./client-ebw9d6ms.js");defineSubscribe();export{YuvaSubscribeElement,defineSubscribe};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{inlineNodes}from"./index-jdxce2se.js";import{el}from"./index-rdzxvj2r.js";import{translate}from"./index-r9f9ttb2.js";var messages=JSON.parse('{"2Hlmdt":["Write a reply…"],"3CApMv":["All discussions"],"3PqJQG":["Nothing to preview."],"4-S4QM":["Unmark as answer"],"5lWFkC":["Sign in"],"8wRl7c":["The opening post was deleted."],"99w-GZ":["Sign in to start a discussion. Your name is shown with your post."],"F_vGso":["Your reply"],"HkXOWm":["This reply was deleted."],"Hw3P48":["Replies: ",["0"]],"ImOQa9":["Reply"],"JfAIiv":["This discussion is locked. New replies are closed."],"Kl3TuI":["Get an e-mail when someone replies or an answer is accepted."],"Klsidc":["Delete this reply?"],"MHrjPM":["Title"],"MKEPCY":["Follow"],"NjUiZ4":["Ask a question, share an idea or describe a problem with this page."],"NrGspR":["Thanks! Your discussion will appear for everyone once the team approves it."],"OVijcR":["Remove your vote (",["0"]," votes)"],"PL0621":["Sign in to reply, vote and follow this discussion."],"PN38hZ":["Your question or idea"],"PZ_kxo":["Keep"],"Pwqkdw":["Loading…"],"RqsQKK":["Your first posts are checked by the team before they appear for everyone."],"Sad2tK":["Sending…"],"VGqKyv":["This discussion is no longer available."],"Vwy_nT":["Markdown is supported."],"YZayoP":["Thanks! Your reply will appear for everyone once the team approves it."],"cnGeoo":["Delete"],"dEgA5A":["Cancel"],"dNOvhg":["Upvote (",["0"]," votes)"],"ePK91l":["Edit"],"i4_LY_":["Write"],"jhu92n":["Mark as answer"],"k4b5_X":["edited"],"n5vqdp":["Start discussion"],"qzVesX":["Edit your post"],"rAl91-":["Delete this discussion?"],"rdUucN":["Preview"],"tfDRzk":["Save"],"y-KXxN":["Accepted answer"],"y6sq5j":["Following"],"z1qf6l":["Start a discussion"]}');var messages2=JSON.parse('{"2Hlmdt":["Antwort schreiben…"],"3CApMv":["Alle Diskussionen"],"3PqJQG":["Noch nichts für die Vorschau."],"4-S4QM":["Antwortmarkierung entfernen"],"5lWFkC":["Anmelden"],"8wRl7c":["Der erste Beitrag wurde gelöscht."],"99w-GZ":["Melden Sie sich an, um eine Diskussion zu starten. Ihr Name wird mit Ihrem Beitrag angezeigt."],"F_vGso":["Ihre Antwort"],"HkXOWm":["Diese Antwort wurde gelöscht."],"Hw3P48":["Antworten: ",["0"]],"ImOQa9":["Antworten"],"JfAIiv":["Diese Diskussion ist gesperrt. Neue Antworten sind nicht möglich."],"Kl3TuI":["Erhalten Sie eine E-Mail, wenn jemand antwortet oder eine Antwort akzeptiert wird."],"Klsidc":["Diese Antwort löschen?"],"MHrjPM":["Titel"],"MKEPCY":["Folgen"],"NjUiZ4":["Stellen Sie eine Frage, teilen Sie eine Idee oder beschreiben Sie ein Problem mit dieser Seite."],"NrGspR":["Danke! Ihre Diskussion ist für alle sichtbar, sobald das Team sie freigibt."],"OVijcR":["Stimme zurückziehen (",["0"]," Stimmen)"],"PL0621":["Melden Sie sich an, um zu antworten, abzustimmen und dieser Diskussion zu folgen."],"PN38hZ":["Ihre Frage oder Idee"],"PZ_kxo":["Behalten"],"Pwqkdw":["Wird geladen…"],"RqsQKK":["Ihre ersten Beiträge prüft das Team, bevor sie für alle sichtbar sind."],"Sad2tK":["Wird gesendet…"],"VGqKyv":["Diese Diskussion ist nicht mehr verfügbar."],"Vwy_nT":["Markdown wird unterstützt."],"YZayoP":["Danke! Ihre Antwort ist für alle sichtbar, sobald das Team sie freigibt."],"cnGeoo":["Löschen"],"dEgA5A":["Abbrechen"],"dNOvhg":["Zustimmen (",["0"]," Stimmen)"],"ePK91l":["Bearbeiten"],"i4_LY_":["Schreiben"],"jhu92n":["Als Antwort markieren"],"k4b5_X":["bearbeitet"],"n5vqdp":["Diskussion starten"],"qzVesX":["Beitrag bearbeiten"],"rAl91-":["Diese Diskussion löschen?"],"rdUucN":["Vorschau"],"tfDRzk":["Speichern"],"y-KXxN":["Akzeptierte Antwort"],"y6sq5j":["Gefolgt"],"z1qf6l":["Diskussion starten"]}');var messages3=JSON.parse('{"2Hlmdt":["Bir yanıt yazın…"],"3CApMv":["Tüm tartışmalar"],"3PqJQG":["Önizlenecek bir şey yok."],"4-S4QM":["Yanıt işaretini kaldır"],"5lWFkC":["Giriş yap"],"8wRl7c":["Açılış gönderisi silindi."],"99w-GZ":["Tartışma başlatmak için giriş yapın. Adınız gönderinizle birlikte gösterilir."],"F_vGso":["Yanıtınız"],"HkXOWm":["Bu yanıt silindi."],"Hw3P48":["Yanıtlar: ",["0"]],"ImOQa9":["Yanıtla"],"JfAIiv":["Bu tartışma kilitli. Yeni yanıt yazılamaz."],"Kl3TuI":["Biri yanıt yazdığında ya da bir yanıt kabul edildiğinde e-posta alın."],"Klsidc":["Bu yanıt silinsin mi?"],"MHrjPM":["Başlık"],"MKEPCY":["Takip et"],"NjUiZ4":["Bir soru sorun, bir fikir paylaşın ya da bu sayfadaki bir sorunu anlatın."],"NrGspR":["Teşekkürler! Tartışmanız ekip onayladığında herkese görünecek."],"OVijcR":["Oyunuzu geri alın (",["0"]," oy)"],"PL0621":["Bu tartışmada yanıt yazmak, oy vermek ve takip etmek için giriş yapın."],"PN38hZ":["Sorunuz ya da fikriniz"],"PZ_kxo":["Kalsın"],"Pwqkdw":["Yükleniyor…"],"RqsQKK":["İlk gönderileriniz herkese görünmeden önce ekip tarafından kontrol edilir."],"Sad2tK":["Gönderiliyor…"],"VGqKyv":["Bu tartışma artık mevcut değil."],"Vwy_nT":["Markdown desteklenir."],"YZayoP":["Teşekkürler! Yanıtınız ekip onayladığında herkese görünecek."],"cnGeoo":["Sil"],"dEgA5A":["Vazgeç"],"dNOvhg":["Oy ver (",["0"]," oy)"],"ePK91l":["Düzenle"],"i4_LY_":["Yaz"],"jhu92n":["Yanıt olarak işaretle"],"k4b5_X":["düzenlendi"],"n5vqdp":["Tartışmayı başlat"],"qzVesX":["Gönderinizi düzenleyin"],"rAl91-":["Bu tartışma silinsin mi?"],"rdUucN":["Önizleme"],"tfDRzk":["Kaydet"],"y-KXxN":["Kabul edilen yanıt"],"y6sq5j":["Takip ediliyor"],"z1qf6l":["Tartışma başlat"]}');var linkPattern=/\[([^\]\n]+)\]\(([^)\s]+)\)/g;function inline(text){let nodes=[],last=0;for(let match of text.matchAll(linkPattern)){let index=match.index??0;if(index>last)nodes.push(...inlineNodes(text.slice(last,index)));let[whole,label="",href=""]=match,url=null;try{url=new URL(href)}catch{}if(url&&(url.protocol==="http:"||url.protocol==="https:")){let a=document.createElement("a");a.href=url.href,a.target="_blank",a.rel="nofollow ugc noopener",a.append(...inlineNodes(label)),nodes.push(a)}else nodes.push(document.createTextNode(whole));last=index+whole.length}if(last<text.length)nodes.push(...inlineNodes(text.slice(last)));return nodes}function block(tag,lines){let element=document.createElement(tag);return element.append(...inline(lines.join(" "))),element}function preview(markdown){let fragment=document.createDocumentFragment(),lines=markdown.replace(/\r\n?/g,`
|
|
2
2
|
`).split(`
|
|
3
3
|
`),paragraph=[],list=null,quote=[],flush=()=>{if(paragraph.length)fragment.append(block("p",paragraph));if(quote.length){let element=document.createElement("blockquote");element.append(preview(quote.join(`
|
|
4
4
|
`))),fragment.append(element)}paragraph=[],quote=[],list=null};for(let i=0;i<lines.length;i++){let line=lines[i]??"",fence=/^\s*(```|~~~)/.exec(line);if(fence){flush();let code=[];while(++i<lines.length&&!(lines[i]??"").trimStart().startsWith(fence[1]??"```"))code.push(lines[i]??"");let pre=document.createElement("pre");pre.append(Object.assign(document.createElement("code"),{textContent:code.join(`
|