UNPKG

embed-fbcmt-client

Version:
309 lines (303 loc) 7.47 kB
'use strict'; var vue = require('vue'); // src/constants.ts var defaults = { color_scheme: "light", lazy: false, mobile: void 0, num_posts: 10, order_by: "reverse_time", lang: "en_US", origin: "*", no_socket: false, active: true, no_popup: false }; // src/client/main.ts function setPropValue(el, prop, value, origin) { if (origin === void 0) { origin = value; value = void 0; } return new Promise((resolve, reject) => { const id = (Number.MAX_SAFE_INTEGER * Math.random()).toString(34); const handler = (event) => { if (event.data?.type === "res::fb:set_value" && id === event.data.id) { const { code } = event.data; if (typeof code !== "string") return; if (code.startsWith("success.")) resolve(); else if (code.startsWith("error.")) reject(Object.assign(new Error(code), { prop })); else console.warn("[res::fb:set_value]: invalid code error '%s'", code); cancel(); } }; let timeout = null; const cancel = () => { if (timeout) clearTimeout(timeout); window.removeEventListener("message", handler); }; window.addEventListener("message", handler); timeout = setTimeout(() => { cancel(); reject(new Error("error.timeout" /* ERROR_TIMEOUT */)); }, 3e4); const res = { id, type: "req::fb:set_value", props: typeof prop === "object" ? prop : { [prop]: value } }; if (el.contentWindow) el.contentWindow.postMessage(res, origin ?? "*"); else reject(); }); } function listenEvent(el, cb) { const handler = (event) => { if (event.source !== el.contentWindow) return; if (event.data?.type !== "emit::fb_embed") return; const typeCode = getTypeCode(event.data.code); if (!typeCode) return; cb({ type: typeCode, code: event.data.code, message: event.data.message }); }; window.addEventListener("message", handler); return () => window.removeEventListener("message", handler); } function listenResize(el, type, cb) { const handler = (event) => { if (event.source !== el.contentWindow) return; if (event.data?.type !== `update::fb_${type}`) return; cb(event.data.value); }; window.addEventListener("message", handler); return () => window.removeEventListener("message", handler); } function getTypeCode(code) { if (code.startsWith("success.")) return "success"; if (code.startsWith("loading.")) return "loading"; if (code.startsWith("error.")) return "error"; return null; } var EmbedFbCmt_default = vue.defineComponent({ props: { color_scheme: { type: String, default: defaults.color_scheme }, href: { type: String, required: true }, lazy: { type: Boolean, default: defaults.lazy }, mobile: { type: Boolean, default: defaults.mobile }, num_posts: { type: Number, default: defaults.num_posts }, order_by: { type: String, default: defaults.order_by }, lang: { type: String, default: defaults.lang }, origin: { type: String, default: defaults.origin }, no_socket: { type: Boolean, default: defaults.no_socket }, active: { type: Boolean, default: defaults.active }, no_popup: { type: Boolean, default: defaults.no_popup }, service: { type: String, default: "https://anime-vsub.github.io/embed-fbcmt" } }, setup(props) { const rootSrc = vue.ref(); vue.watch( () => props.service, (service) => { const query = new URLSearchParams( props ); query.delete("service"); rootSrc.value = new URL(`?${query}`, service).toString(); }, { immediate: true } ); const commentRef = vue.ref(); vue.watch(props, async (props2) => { const cloned = { ...props2 }; delete cloned.service; await setPropValue2(commentRef, cloned); }); const height = useEmbedHeight(commentRef); return () => vue.h("iframe", { src: rootSrc.value, ref: commentRef, frameborder: "0", allowtransparency: "true", allowfullscreen: "true", scrolling: "no", width: "100%", height: "100%", allow: "encrypted-media", sandbox: "allow-forms allow-scripts allow-same-origin allow-top-navigation allow-top-navigation-by-user-activation allow-popups allow-popups-to-escape-sandbox", style: { height: `${height.value}px` } }); } }); // src/client/vue.ts function isComponent(el) { return typeof el.$el !== "undefined"; } function useEmbed(el) { const code = vue.ref({ code: "pending" /* PENDING */ }); const loading = vue.ref(false); const error = vue.ref(); let cancelListenEvent = null; if (!vue.isRef(el)) el = vue.ref(el); vue.watch( el, (el2) => { if (isComponent(el2)) el2 = el2.$el; cancelListenEvent?.(); loading.value = false; error.value = void 0; code.value = { code: "pending" /* PENDING */ }; if (!el2) return; cancelListenEvent = listenEvent(el2, (event) => { code.value = event; if (event.type === "loading") { error.value = void 0; loading.value = true; } else if (event.type === "error") { loading.value = false; error.value = Object.assign(new Error(event.message), { code: event.type }); } else { loading.value = false; error.value = void 0; } }); }, { immediate: true } ); vue.onBeforeUnmount(() => cancelListenEvent?.()); return { code, loading, error }; } function useEmbedSize(el) { let cancelResizWEvent = null; let cancelResizHEvent = null; const width = vue.ref(0); const height = vue.ref(0); if (!vue.isRef(el)) el = vue.ref(el); vue.watch(el, (el2) => { if (isComponent(el2)) el2 = el2.$el; cancelResizWEvent?.(); cancelResizHEvent?.(); if (!el2) return; cancelResizWEvent = listenResize( el2, "width", (value) => width.value = value ); cancelResizHEvent = listenResize( el2, "height", (value) => height.value = value ); }); vue.onBeforeUnmount(() => { cancelResizWEvent?.(); cancelResizHEvent?.(); }); return { width, height }; } function useEmbedHeight(el) { let cancelResizHEvent = null; const height = vue.ref(0); if (!vue.isRef(el)) el = vue.ref(el); vue.watch(el, (el2) => { if (isComponent(el2)) el2 = el2.$el; cancelResizHEvent?.(); if (!el2) return; cancelResizHEvent = listenResize( el2, "height", (value) => height.value = value ); }); vue.onBeforeUnmount(() => { cancelResizHEvent?.(); }); return height; } async function setPropValue2(el, prop, value, origin) { if (vue.isRef(el)) el = el.value; if (isComponent(el)) el = el.$el; if (el) { await setPropValue( el, prop, value, origin ); } } exports.EmbedFbCmt = EmbedFbCmt_default; exports.listenResize = listenResize; exports.setPropValue = setPropValue2; exports.useEmbed = useEmbed; exports.useEmbedHeight = useEmbedHeight; exports.useEmbedSize = useEmbedSize;