diff --git a/docusaurus.config.js b/docusaurus.config.js index d9b901cc6..f73c128a3 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -143,6 +143,14 @@ module.exports = { } }, themeConfig: { + image: 'img/og-default-suite.png', + metadata: [ + { property: 'og:type', content: 'website' }, + { property: 'og:site_name', content: 'DHTMLX Suite Docs' }, + { property: 'og:locale', content: 'en_US' }, + { name: 'twitter:card', content: 'summary_large_image' }, + { name: 'twitter:site', content: '@dhtmlx' } + ], algolia: { // This is a read-only, search-only key served directly by the front-end, managed by Algolia via their // free DocSearch program. The key is not sensitive. See https://docsearch.algolia.com/ for more details. diff --git a/src/components/StructuredData/index.js b/src/components/StructuredData/index.js new file mode 100644 index 000000000..a32562505 --- /dev/null +++ b/src/components/StructuredData/index.js @@ -0,0 +1,102 @@ +import React from 'react'; +import Head from '@docusaurus/Head'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import { useBaseUrlUtils } from '@docusaurus/useBaseUrl'; + +const SITE_NAME = 'DHTMLX Suite Docs'; +const PRODUCT_NAME = 'DHTMLX Suite'; +const PRODUCT_URL = 'https://dhtmlx.com/docs/products/dhtmlxSuite/'; + +function resolveType(pathname) { + const path = (pathname || '').replace(/\/+$/, ''); + if (path === '' || path === '/suite') return 'SoftwareApplication'; + if (/\/api(\/|$)/.test(path)) return 'APIReference'; + return 'TechArticle'; +} + +function buildJsonLd({ type, title, description, url, image, siteUrl }) { + const base = { + '@context': 'https://schema.org', + headline: title, + name: title, + description, + url, + image, + inLanguage: 'en-US', + isPartOf: { + '@type': 'WebSite', + name: SITE_NAME, + url: siteUrl + } + }; + + if (type === 'SoftwareApplication') { + return { + '@context': 'https://schema.org', + '@type': 'SoftwareApplication', + name: PRODUCT_NAME, + description, + url, + image, + applicationCategory: 'DeveloperApplication', + operatingSystem: 'Cross-platform', + offers: { + '@type': 'Offer', + url: PRODUCT_URL, + priceCurrency: 'USD' + } + }; + } + + if (type === 'APIReference') { + return { + ...base, + '@type': 'APIReference', + programmingModel: 'JavaScript', + about: { + '@type': 'SoftwareApplication', + name: PRODUCT_NAME, + applicationCategory: 'DeveloperApplication' + } + }; + } + + return { + ...base, + '@type': 'TechArticle', + proficiencyLevel: 'Beginner', + dependencies: PRODUCT_NAME, + about: { + '@type': 'SoftwareApplication', + name: PRODUCT_NAME, + applicationCategory: 'DeveloperApplication' + } + }; +} + +export default function StructuredData({ title, description, pathname, image }) { + const { siteConfig } = useDocusaurusContext(); + const { withBaseUrl } = useBaseUrlUtils(); + + const siteUrl = siteConfig.url + siteConfig.baseUrl.replace(/\/$/, ''); + const url = siteConfig.url + withBaseUrl(pathname || '/'); + const absoluteImage = image ? withBaseUrl(image, { absolute: true }) : undefined; + + const type = resolveType(pathname); + const jsonLd = buildJsonLd({ + type, + title, + description, + url, + image: absoluteImage, + siteUrl + }); + + return ( + + + + ); +} diff --git a/src/theme/DocItem/Metadata/index.js b/src/theme/DocItem/Metadata/index.js new file mode 100644 index 000000000..91b5fb9c5 --- /dev/null +++ b/src/theme/DocItem/Metadata/index.js @@ -0,0 +1,31 @@ +import React from 'react'; +import Head from '@docusaurus/Head'; +import { useLocation } from '@docusaurus/router'; +import DocItemMetadata from '@theme-original/DocItem/Metadata'; +import { useDoc } from '@docusaurus/plugin-content-docs/client'; +import StructuredData from '@site/src/components/StructuredData'; + +export default function DocItemMetadataWrapper(props) { + const { metadata, frontMatter, assets } = useDoc(); + const { pathname } = useLocation(); + + const title = metadata.title; + const description = metadata.description; + const image = assets.image ?? frontMatter.image; + + return ( + <> + + + {title && } + {description && } + + + + ); +} diff --git a/static/img/og-default-suite.png b/static/img/og-default-suite.png new file mode 100644 index 000000000..ab03a635a Binary files /dev/null and b/static/img/og-default-suite.png differ