fledged out analytics, self gather, remove vercel speed insights
This commit is contained in:
@@ -84,6 +84,104 @@ export default function PostBodyClient(props: PostBodyClientProps) {
|
||||
});
|
||||
};
|
||||
|
||||
const processVideos = () => {
|
||||
if (!contentRef) return;
|
||||
|
||||
// Handle direct video elements
|
||||
const videoElements = contentRef.querySelectorAll("video");
|
||||
|
||||
videoElements.forEach((video) => {
|
||||
// Ensure videos play inline and don't trigger downloads
|
||||
video.setAttribute("playsinline", "");
|
||||
video.setAttribute("controls", "");
|
||||
|
||||
// Remove download attribute if present
|
||||
video.removeAttribute("download");
|
||||
|
||||
// Ensure proper MIME types on source elements
|
||||
const sources = video.querySelectorAll("source");
|
||||
sources.forEach((source) => {
|
||||
const src = source.getAttribute("src");
|
||||
if (src) {
|
||||
// Remove download attribute from sources
|
||||
source.removeAttribute("download");
|
||||
|
||||
// Set correct type attribute if missing
|
||||
if (!source.hasAttribute("type")) {
|
||||
if (src.endsWith(".mp4")) {
|
||||
source.setAttribute("type", "video/mp4");
|
||||
} else if (src.endsWith(".webm")) {
|
||||
source.setAttribute("type", "video/webm");
|
||||
} else if (src.endsWith(".ogg")) {
|
||||
source.setAttribute("type", "video/ogg");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// If video has direct src attribute, ensure type is set
|
||||
const videoSrc = video.getAttribute("src");
|
||||
if (videoSrc && !video.hasAttribute("type")) {
|
||||
if (videoSrc.endsWith(".mp4")) {
|
||||
video.setAttribute("type", "video/mp4");
|
||||
} else if (videoSrc.endsWith(".webm")) {
|
||||
video.setAttribute("type", "video/webm");
|
||||
} else if (videoSrc.endsWith(".ogg")) {
|
||||
video.setAttribute("type", "video/ogg");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Handle iframes with video sources - replace with proper video tags
|
||||
const iframes = contentRef.querySelectorAll("iframe");
|
||||
iframes.forEach((iframe) => {
|
||||
const src = iframe.getAttribute("src");
|
||||
if (
|
||||
src &&
|
||||
(src.endsWith(".mp4") ||
|
||||
src.endsWith(".mov") ||
|
||||
src.endsWith(".webm") ||
|
||||
src.endsWith(".ogg"))
|
||||
) {
|
||||
// Create a proper video element
|
||||
const video = document.createElement("video");
|
||||
video.setAttribute("controls", "");
|
||||
video.setAttribute("playsinline", "");
|
||||
video.setAttribute("preload", "metadata");
|
||||
video.style.maxWidth = "100%";
|
||||
video.style.height = "auto";
|
||||
|
||||
// Set appropriate type based on file extension
|
||||
let videoType = "video/mp4";
|
||||
if (src.endsWith(".mov")) {
|
||||
videoType = "video/mp4"; // MOV files are typically H.264 which plays as mp4
|
||||
} else if (src.endsWith(".webm")) {
|
||||
videoType = "video/webm";
|
||||
} else if (src.endsWith(".ogg")) {
|
||||
videoType = "video/ogg";
|
||||
}
|
||||
|
||||
video.setAttribute("type", videoType);
|
||||
video.src = src;
|
||||
|
||||
// Replace the iframe with the video element
|
||||
const parent = iframe.parentElement;
|
||||
if (parent) {
|
||||
parent.replaceChild(video, iframe);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Also check for any anchor tags wrapping videos that might have download attribute
|
||||
const videoLinks = contentRef.querySelectorAll("a");
|
||||
videoLinks.forEach((link) => {
|
||||
const hasVideo = link.querySelector("video");
|
||||
if (hasVideo) {
|
||||
link.removeAttribute("download");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const processReferences = () => {
|
||||
if (!contentRef) return;
|
||||
|
||||
@@ -235,6 +333,7 @@ export default function PostBodyClient(props: PostBodyClientProps) {
|
||||
|
||||
onMount(() => {
|
||||
setTimeout(() => {
|
||||
processVideos();
|
||||
processReferences();
|
||||
if (props.hasCodeBlock) {
|
||||
processCodeBlocks();
|
||||
@@ -286,6 +385,7 @@ export default function PostBodyClient(props: PostBodyClientProps) {
|
||||
createEffect(() => {
|
||||
if (props.body && contentRef) {
|
||||
setTimeout(() => {
|
||||
processVideos();
|
||||
processReferences();
|
||||
if (props.hasCodeBlock) {
|
||||
processCodeBlocks();
|
||||
|
||||
@@ -298,8 +298,23 @@ const IframeEmbed = Node.create<IframeOptions>({
|
||||
return {
|
||||
setIframe:
|
||||
(options: { src: string }) =>
|
||||
({ tr, dispatch }) => {
|
||||
({ tr, dispatch, editor }) => {
|
||||
const { selection } = tr;
|
||||
|
||||
// Check if the src is a direct video file
|
||||
const src = options.src || "";
|
||||
const isVideoFile = /\.(mp4|mov|webm|ogg)(\?.*)?$/i.test(src);
|
||||
|
||||
if (isVideoFile) {
|
||||
// Insert a proper video tag instead of iframe
|
||||
if (dispatch) {
|
||||
const videoHTML = `<video src="${src}" controls playsinline style="max-width: 100%; height: auto;"></video>`;
|
||||
editor.commands.insertContent(videoHTML);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// For non-video URLs, create iframe as normal
|
||||
const node = this.type.create(options);
|
||||
|
||||
if (dispatch) {
|
||||
|
||||
Reference in New Issue
Block a user