diff --git a/docusaurus.config.js b/docusaurus.config.js index 79830f2be..0b3924729 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -131,7 +131,6 @@ module.exports = { url: 'https://docs.dhtmlx.com', baseUrl: '/diagram/', onBrokenLinks: 'warn', - onBrokenMarkdownLinks: 'warn', onBrokenAnchors: 'warn', // onBrokenLinks: 'ignore', // !!! TODO, make to warn before release // onBrokenAnchors: 'ignore', // !!! TODO, make to warn before release @@ -146,6 +145,14 @@ module.exports = { } }, themeConfig: { + image: 'img/og-default-diagram.png', + metadata: [ + { property: 'og:type', content: 'website' }, + { property: 'og:site_name', content: 'DHTMLX Diagram Docs' }, + { property: 'og:locale', content: 'en_US' }, + { name: 'twitter:card', content: 'summary_large_image' }, + { name: 'twitter:site', content: '@dhtmlx' } + ], /*colorMode: { // "light" | "dark" defaultMode: 'light', diff --git a/src/components/StructuredData/index.js b/src/components/StructuredData/index.js new file mode 100644 index 000000000..bdfd29dc0 --- /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 Diagram Docs'; +const PRODUCT_NAME = 'DHTMLX Diagram'; +const PRODUCT_URL = 'https://dhtmlx.com/docs/products/dhtmlxDiagram/'; + +function resolveType(pathname) { + const path = (pathname || '').replace(/\/+$/, ''); + if (path === '' || path === '/diagram') 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-diagram.png b/static/img/og-default-diagram.png new file mode 100644 index 000000000..800b0e648 Binary files /dev/null and b/static/img/og-default-diagram.png differ