import { useSupportArticle } from '@help-center/hooks/useSupportArticles'; import { useKnowledgeBaseStore } from '@help-center/state/knowledge-base'; import apiFetch from '@wordpress/api-fetch'; import { Spinner } from '@wordpress/components'; import { useEffect, useRef, useState } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import parse from 'html-react-parser'; export const Article = () => { const { articles, pushArticle, popArticle, updateTitle } = useKnowledgeBaseStore(); const [openedErrorUrl, setOpenedErrorUrl] = useState(); const [fetching, setFetching] = useState(false); const articleRef = useRef(); const slug = articles?.[0]?.slug; const { data: article, error, loading } = useSupportArticle(slug); const title = article?.title; const getArticleRedirect = (url) => apiFetch({ path: `/extendify/v1/help-center/get-redirect?path=${url}`, }); useEffect(() => { if (!error) return setOpenedErrorUrl(false); // If there's an error, then open the url once if (openedErrorUrl) return; setOpenedErrorUrl(true); popArticle(); window.open( `https://wordpress.org/documentation/article/${slug}`, '_blank', ); }, [error, slug, openedErrorUrl, popArticle]); useEffect(() => { if (!slug || !title) return; updateTitle(slug, title); }, [title, updateTitle, slug]); useEffect(() => { if (!articleRef.current) return; const links = articleRef.current?.querySelectorAll('a'); // a small fix to make sure the images fit within the modal const figures = articleRef.current?.querySelectorAll('figure'); const images = articleRef.current?.querySelectorAll('img'); figures.forEach((figure) => { figure.classList.add('mx-auto'); figure.classList.add('my-4'); figure.classList.add('block'); figure.classList.add('w-full'); figure.classList.remove('wp-block-image'); }); images.forEach((image) => { image.classList.add('object-contain'); image.classList.add('max-w-[400px]'); image.classList.add('max-h-[250px]'); }); const handleInternal = async (e) => { e.preventDefault(); // In that case, event.ctrlKey does the trick. if (e.ctrlKey || e.metaKey) { e.stopPropagation(); return window.open(e.target.href, '_blank'); } // Could be the parent element so check both const link = e.target?.href ?? e.target?.closest('a')?.href; const { pathname } = new URL(link); const slug = pathname.split('/').filter(Boolean)?.at(-1); // Both the new docs site and the old may have redirects setFetching(true); const data = await getArticleRedirect(pathname); setFetching(false); if (!data) { // If nothing useful was returned, it could be the new docs site if (pathname.startsWith('/documentation/article/')) { return pushArticle({ slug, title: undefined }); } // But if not then just open the link in a new tab return window.open(`https://wordpress.org${pathname}`, '_blank'); } // Finally load the article pushArticle({ slug: data.split('/').filter(Boolean)?.at(-1) }); }; const handleExternal = (e) => { e.preventDefault(); window.open(e.target.href, '_blank'); }; const handleNoOp = (e) => e.preventDefault(); links.forEach((link) => { const { hash, host, pathname } = new URL(link.href); // Hash links should be disabled since they don't work properly if ( (hash && host === window.location.host) || pathname.startsWith('/support/category') ) { link.addEventListener('click', handleNoOp); link.setAttribute('aria-disabled', 'true'); link.classList.add('link-disabled'); return; } // if link is to an image or a file, remove it const pattern = /\.(jpg|jpeg|png|gif|pdf|doc|docx|xls|xlsx|ppt|pptx)$/; if (pathname.match(pattern)) { link.addEventListener('click', handleNoOp); return; } if ( pathname.startsWith('/documentation/article') || pathname.startsWith('/support/article') ) { link.addEventListener('click', handleInternal); return; } // If the link is something else, then open in a new tab link.addEventListener('click', handleExternal); const svg = ''; const svgEl = document.createElement('span'); svgEl.innerHTML = svg; link.appendChild(svgEl); }); return () => { links.forEach((link) => { link?.removeEventListener('click', handleInternal); link?.removeEventListener('click', handleExternal); link?.removeEventListener('click', handleNoOp); }); }; }, [article, pushArticle]); if (loading || fetching) { return (
); } if (error) { return (
{__('There was an error loading this article', 'extendify-local')}
); } return (

{title}

{article?.content && parse(article?.content)}
); };