mirror of
https://github.com/mattermost/mattermost.git
synced 2026-11-03 20:56:57 -06:00
* docs: self-host fonts, images, and OpenAPI icons; block build egress Stop hotlinking GitHub/user-images and Google Fonts on the docs site, replace embedded video iframes with links, and fail CI when a build would fetch off-origin resources (closed allowlist for the security-updates feed). Co-authored-by: Cursor <cursoragent@cursor.com> * docs: address CodeRabbit egress review findings Scan an offline (no-Algolia) rebuild in Docs CI, tighten ATTR/getAttr boundaries, flag remote template-literal prefixes before ${, and add alt text for the self-hosted plugin-management image. Co-authored-by: Cursor <cursoragent@cursor.com> * docs: replace egress fixture tree with in-memory unit tests Keep scanner coverage without committing dozens of tiny HTML/CSS/JS fixture files. scanSources takes string maps; CLI smoke uses a temp dir. Co-authored-by: Cursor <cursoragent@cursor.com> * docs: keep YouTube/Wistia embeds on hosted site Restore in-page players for the public docs. Allowlist those hosts in check-egress; the offline packager strips them for airgap. Co-authored-by: Cursor <cursoragent@cursor.com> * docs: simplify hosted-embed allowlist to base domains Co-authored-by: Cursor <cursoragent@cursor.com> * docs: tighten hosted-embed allowlist to player kinds and paths Only iframe/script/img player URLs pass; fetch() and other loads to YouTube/Wistia hosts still fail egress. Co-authored-by: Cursor <cursoragent@cursor.com> * docs: allow Wistia swatch preload in hosted-embed egress check The organize-conversations embed emits link[rel=preload] for the swatch; kind-scoped allowlisting missed it and failed Docs CI. Co-authored-by: Cursor <cursoragent@cursor.com> * docs: use getAttr boundary for script hasSrc check \b matches inside data-src, so the old hasSrc could skip scanning an inline script body. Align with ATTR/getAttr and cover the case in tests. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
288 lines
8.9 KiB
TypeScript
288 lines
8.9 KiB
TypeScript
import {themes as prismThemes} from 'prism-react-renderer';
|
|
import type {Config} from '@docusaurus/types';
|
|
import type * as Preset from '@docusaurus/preset-classic';
|
|
// Active redirects (legacy Sphinx URLs → migrated MDX paths). Bulk-extracted
|
|
// during the docs migration, maintained by hand since — add entries directly
|
|
// to the JSON when a page moves or is removed.
|
|
import activeRedirects from './sidebars/active-redirects.json';
|
|
|
|
// Multi-instance docs setup with three top-level navigations:
|
|
// / → Documentation (admin / end-user) sources: ../docs
|
|
// /developers → Developers (contribute / integrate) sources: ../develop
|
|
// /api → API Reference (OpenAPI-generated) sources: ../api
|
|
// See PLAN.md §3.1 for the IA, §3.2 for design tokens.
|
|
|
|
// Docusaurus's Algolia schema rejects an empty `appId`/`apiKey`, so the
|
|
// block is only included when both are set. Without credentials the search
|
|
// bar is simply omitted (rather than rendered as an inert element), which
|
|
// keeps local and CI builds green.
|
|
const algoliaAppId = process.env.ALGOLIA_APP_ID;
|
|
const algoliaApiKey = process.env.ALGOLIA_SEARCH_API_KEY;
|
|
const algoliaThemeConfig =
|
|
algoliaAppId && algoliaApiKey
|
|
? {
|
|
algolia: {
|
|
appId: algoliaAppId,
|
|
apiKey: algoliaApiKey,
|
|
indexName: 'mattermost-docs',
|
|
contextualSearch: true,
|
|
searchPagePath: 'search',
|
|
searchParameters: {
|
|
optionalFilters: [
|
|
'docusaurus_tag:docs-documentation-current<score=3>',
|
|
'docusaurus_tag:docs-developers-current<score=2>',
|
|
'docusaurus_tag:docs-api-current<score=1>',
|
|
],
|
|
},
|
|
},
|
|
}
|
|
: {};
|
|
|
|
const config: Config = {
|
|
title: 'Mattermost Documentation',
|
|
tagline: 'Mission in Motion',
|
|
favicon: 'img/brand/icon-denim.svg',
|
|
|
|
future: {
|
|
v4: true,
|
|
},
|
|
|
|
url: 'https://docs.mattermost.com',
|
|
baseUrl: process.env.BASE_URL ?? '/',
|
|
trailingSlash: false,
|
|
|
|
organizationName: 'mattermost',
|
|
projectName: 'mattermost',
|
|
|
|
// Broken-link / broken-image policy. During the Phase 4 (developer docs)
|
|
// and Phase 5 (main docs) migrations, content references images and
|
|
// anchors that haven't been migrated yet — `warn` keeps the build green
|
|
// while the unconverted set shows up as warnings we can grep for.
|
|
// Tighten to `throw` after each migration phase completes.
|
|
onBrokenLinks: 'warn',
|
|
|
|
markdown: {
|
|
mermaid: true,
|
|
hooks: {
|
|
onBrokenMarkdownLinks: 'warn',
|
|
onBrokenMarkdownImages: 'warn',
|
|
},
|
|
},
|
|
|
|
i18n: {
|
|
defaultLocale: 'en',
|
|
locales: ['en'],
|
|
},
|
|
|
|
// Fonts are self-hosted from src/css/fonts (see the README there).
|
|
|
|
// Use the classic preset for the default Documentation instance.
|
|
// Developers and API are added as separate plugin instances below
|
|
// to give each its own routeBasePath and sidebar.
|
|
presets: [
|
|
[
|
|
'classic',
|
|
{
|
|
docs: {
|
|
id: 'documentation',
|
|
path: '../main',
|
|
routeBasePath: '/',
|
|
sidebarPath: './sidebars/documentation.ts',
|
|
editUrl: 'https://github.com/mattermost/mattermost/tree/master/docs/main/',
|
|
},
|
|
blog: false,
|
|
theme: {
|
|
customCss: ['./src/css/fonts.css', './src/css/tokens.css', './src/css/custom.css'],
|
|
},
|
|
} satisfies Preset.Options,
|
|
],
|
|
],
|
|
|
|
plugins: [
|
|
[
|
|
'@docusaurus/plugin-content-docs',
|
|
{
|
|
id: 'developers',
|
|
path: '../develop',
|
|
routeBasePath: '/developers',
|
|
sidebarPath: './sidebars/developers.ts',
|
|
editUrl: 'https://github.com/mattermost/mattermost/tree/master/docs/develop/',
|
|
},
|
|
],
|
|
[
|
|
'@docusaurus/plugin-content-docs',
|
|
{
|
|
id: 'api',
|
|
path: '../api',
|
|
routeBasePath: '/api',
|
|
sidebarPath: './sidebars/api.ts',
|
|
editUrl: 'https://github.com/mattermost/mattermost/tree/master/docs/api/',
|
|
// Required for endpoint pages generated by docusaurus-plugin-openapi-docs.
|
|
docItemComponent: '@theme/ApiItem',
|
|
},
|
|
],
|
|
[
|
|
'@docusaurus/plugin-client-redirects',
|
|
{
|
|
// Legacy URL → migrated MDX path. Pre-filtered to entries whose
|
|
// target exists, so the build never breaks on a missing target.
|
|
redirects: activeRedirects.redirects,
|
|
},
|
|
],
|
|
// Generates API reference pages from the OpenAPI bundle produced by
|
|
// build-openapi.mjs
|
|
[
|
|
'docusaurus-plugin-openapi-docs',
|
|
{
|
|
id: 'api-generator',
|
|
docsPluginId: 'api',
|
|
config: {
|
|
mattermost: {
|
|
specPath: 'openapi/mattermost-openapi-v4.yaml',
|
|
outputDir: '../api/reference',
|
|
sidebarOptions: {
|
|
groupPathsBy: 'tag',
|
|
categoryLinkSource: 'tag',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
],
|
|
],
|
|
|
|
// Theme for the API endpoint pages (parameter tables, request/response
|
|
// schemas, code-sample picker). Layered on the classic preset theme.
|
|
themes: ['docusaurus-theme-openapi-docs', '@docusaurus/theme-mermaid'],
|
|
|
|
themeConfig: {
|
|
image: 'img/brand/logo-horizontal-denim.svg',
|
|
colorMode: {
|
|
defaultMode: 'light',
|
|
respectPrefersColorScheme: true,
|
|
},
|
|
navbar: {
|
|
title: '',
|
|
logo: {
|
|
alt: 'Mattermost',
|
|
// Navbar is denim in both light and dark mode, so white logo always.
|
|
src: 'img/brand/logo-horizontal-white.svg',
|
|
srcDark: 'img/brand/logo-horizontal-white.svg',
|
|
},
|
|
items: [
|
|
{
|
|
type: 'docSidebar',
|
|
docsPluginId: 'documentation',
|
|
sidebarId: 'documentation',
|
|
position: 'left',
|
|
label: 'Documentation',
|
|
},
|
|
{
|
|
type: 'docSidebar',
|
|
docsPluginId: 'developers',
|
|
sidebarId: 'developers',
|
|
position: 'left',
|
|
label: 'Developers',
|
|
},
|
|
{
|
|
type: 'docSidebar',
|
|
docsPluginId: 'api',
|
|
sidebarId: 'api',
|
|
position: 'left',
|
|
label: 'API',
|
|
},
|
|
{
|
|
href: 'https://github.com/mattermost/mattermost',
|
|
label: 'GitHub',
|
|
position: 'right',
|
|
},
|
|
],
|
|
},
|
|
footer: {
|
|
style: 'dark',
|
|
logo: {
|
|
alt: 'Mattermost — Mission in Motion',
|
|
src: 'img/brand/logo-horizontal-white.svg',
|
|
width: 180,
|
|
},
|
|
links: [
|
|
{
|
|
title: 'Documentation',
|
|
items: [
|
|
{label: 'Product Overview', to: '/'},
|
|
{label: 'Deployment Guide', to: '/'},
|
|
{label: 'Administration Guide', to: '/'},
|
|
],
|
|
},
|
|
{
|
|
title: 'Developers',
|
|
items: [
|
|
{label: 'Contribute', to: '/developers'},
|
|
{label: 'Integrate & Extend', to: '/developers'},
|
|
{label: 'API Reference', to: '/api'},
|
|
],
|
|
},
|
|
{
|
|
title: 'Community',
|
|
items: [
|
|
{label: 'GitHub', href: 'https://github.com/mattermost/mattermost'},
|
|
{label: 'Forum', href: 'https://forum.mattermost.com/'},
|
|
],
|
|
},
|
|
],
|
|
copyright: `Copyright © ${new Date().getFullYear()} Mattermost, Inc. All rights reserved.`,
|
|
},
|
|
...algoliaThemeConfig,
|
|
prism: {
|
|
theme: prismThemes.github,
|
|
darkTheme: prismThemes.dracula,
|
|
additionalLanguages: ['bash', 'powershell', 'json', 'yaml', 'go', 'python'],
|
|
},
|
|
mermaid: {
|
|
theme: {light: 'base', dark: 'dark'},
|
|
options: {
|
|
themeVariables: {
|
|
fontSize: '14px',
|
|
primaryColor: '#0984e3',
|
|
primaryTextColor: '#ffffff',
|
|
primaryBorderColor: '#2d3436',
|
|
lineColor: '#0745a1',
|
|
secondaryColor: '#0984e3',
|
|
tertiaryColor: '#d63031',
|
|
mainBkg: '#ffffff',
|
|
textColor: '#2d3436',
|
|
taskBkgColor: '#0984e3',
|
|
taskTextColor: '#ffffff',
|
|
taskTextLightColor: '#ffffff',
|
|
taskTextDarkColor: '#ffffff',
|
|
activeTaskBkgColor: '#0984e3',
|
|
activeTaskBorderColor: '#2d3436',
|
|
doneTaskBkgColor: '#0984e3',
|
|
doneTaskBorderColor: '#2d3436',
|
|
critBkgColor: '#d63031',
|
|
critBorderColor: '#2d3436',
|
|
},
|
|
gantt: {
|
|
fontSize: 14,
|
|
sectionFontSize: 14,
|
|
barHeight: 28,
|
|
barGap: 6,
|
|
topPadding: 50,
|
|
leftPadding: 75,
|
|
gridLineStartPadding: 35,
|
|
},
|
|
},
|
|
},
|
|
// Code-sample tabs shown on every endpoint page, in display order.
|
|
// First entry is the default selected tab (curl).
|
|
languageTabs: [
|
|
{highlight: 'bash', language: 'curl', logoClass: 'curl'},
|
|
{highlight: 'powershell', language: 'powershell', logoClass: 'powershell'},
|
|
{highlight: 'python', language: 'python', logoClass: 'python'},
|
|
{highlight: 'javascript', language: 'nodejs', logoClass: 'nodejs', label: 'Node'},
|
|
{highlight: 'go', language: 'go', logoClass: 'go'},
|
|
],
|
|
} satisfies Preset.ThemeConfig,
|
|
};
|
|
|
|
export default config;
|