mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-12-23 12:46:36 +01:00
Compare commits
2 Commits
develop
...
fix/align-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a325ae8f3 | ||
|
|
bc53201551 |
@@ -8,7 +8,7 @@ import type { CanonicalUrlConfig } from './canonical-urls.js';
|
||||
*/
|
||||
export const canonicalConfig: CanonicalUrlConfig = {
|
||||
// Base URL for the Mermaid documentation site
|
||||
baseUrl: 'https://mermaid.ai/open-source',
|
||||
baseUrl: 'https://docs.mermaidchart.com',
|
||||
|
||||
// Disable automatic generation - only use specificCanonicalUrls
|
||||
autoGenerate: false,
|
||||
@@ -57,6 +57,93 @@ export const canonicalConfig: CanonicalUrlConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Pages that should have specific canonical URLs
|
||||
*
|
||||
* Since autoGenerate is set to false, ONLY pages listed here will get canonical URLs.
|
||||
*
|
||||
* Usage: Add entries to this object where the key is the relative path
|
||||
* of the markdown file and the value is the desired canonical URL.
|
||||
*
|
||||
* Examples:
|
||||
* - 'intro/index.md': 'https://docs.mermaidchart.com/intro/index.html'
|
||||
* - 'syntax/flowchart.md': 'https://docs.mermaidchart.com/mermaid-oss/syntax/flowchart.html'
|
||||
* - 'config/configuration.md': 'https://docs.mermaidchart.com/mermaid-oss/config/configuration.html'
|
||||
*/
|
||||
export const specificCanonicalUrls: Record<string, string> = {
|
||||
// Add your specific canonical URLs here
|
||||
// Example:
|
||||
// 'syntax/flowchart.md': 'https://docs.mermaidchart.com/mermaid-oss/syntax/flowchart.html',
|
||||
|
||||
// Intro section
|
||||
'intro/index.md': 'https://docs.mermaidchart.com/intro/index.html',
|
||||
'intro/getting-started.md':
|
||||
'https://docs.mermaidchart.com/mermaid-oss/intro/getting-started.html',
|
||||
'intro/syntax-reference.md':
|
||||
'https://docs.mermaidchart.com/mermaid-oss/intro/syntax-reference.html',
|
||||
|
||||
// Syntax section
|
||||
'syntax/flowchart.md': 'https://docs.mermaidchart.com/mermaid-oss/syntax/flowchart.html',
|
||||
'syntax/sequenceDiagram.md':
|
||||
'https://docs.mermaidchart.com/mermaid-oss/syntax/sequenceDiagram.html',
|
||||
'syntax/classDiagram.md': 'https://docs.mermaidchart.com/mermaid-oss/syntax/classDiagram.html',
|
||||
'syntax/stateDiagram.md': 'https://docs.mermaidchart.com/mermaid-oss/syntax/stateDiagram.html',
|
||||
'syntax/entityRelationshipDiagram.md':
|
||||
'https://docs.mermaidchart.com/mermaid-oss/syntax/entityRelationshipDiagram.html',
|
||||
'syntax/userJourney.md': 'https://docs.mermaidchart.com/mermaid-oss/syntax/userJourney.html',
|
||||
'syntax/gantt.md': 'https://docs.mermaidchart.com/mermaid-oss/syntax/gantt.html',
|
||||
'syntax/pie.md': 'https://docs.mermaidchart.com/mermaid-oss/syntax/pie.html',
|
||||
'syntax/quadrantChart.md': 'https://docs.mermaidchart.com/mermaid-oss/syntax/quadrantChart.html',
|
||||
'syntax/requirementDiagram.md':
|
||||
'https://docs.mermaidchart.com/mermaid-oss/syntax/requirementDiagram.html',
|
||||
'syntax/mindmap.md': 'https://docs.mermaidchart.com/mermaid-oss/syntax/mindmap.html',
|
||||
'syntax/timeline.md': 'https://docs.mermaidchart.com/mermaid-oss/syntax/timeline.html',
|
||||
'syntax/gitgraph.md': 'https://docs.mermaidchart.com/mermaid-oss/syntax/gitgraph.html',
|
||||
'syntax/c4.md': 'https://docs.mermaidchart.com/mermaid-oss/syntax/c4.html',
|
||||
'syntax/sankey.md': 'https://docs.mermaidchart.com/mermaid-oss/syntax/sankey.html',
|
||||
'syntax/xyChart.md': 'https://docs.mermaidchart.com/mermaid-oss/syntax/xyChart.html',
|
||||
'syntax/block.md': 'https://docs.mermaidchart.com/mermaid-oss/syntax/block.html',
|
||||
'syntax/packet.md': 'https://docs.mermaidchart.com/mermaid-oss/syntax/packet.html',
|
||||
'syntax/kanban.md': 'https://docs.mermaidchart.com/mermaid-oss/syntax/kanban.html',
|
||||
'syntax/architecture.md': 'https://docs.mermaidchart.com/mermaid-oss/syntax/architecture.html',
|
||||
'syntax/radar.md': 'https://docs.mermaidchart.com/mermaid-oss/syntax/radar.html',
|
||||
'syntax/examples.md': 'https://docs.mermaidchart.com/mermaid-oss/syntax/examples.html',
|
||||
|
||||
// Config section
|
||||
'config/configuration.md': 'https://docs.mermaidchart.com/mermaid-oss/config/configuration.html',
|
||||
'config/usage.md': 'https://docs.mermaidchart.com/mermaid-oss/config/usage.html',
|
||||
'config/icons.md': 'https://docs.mermaidchart.com/mermaid-oss/config/icons.html',
|
||||
'config/directives.md': 'https://docs.mermaidchart.com/mermaid-oss/config/directives.html',
|
||||
'config/theming.md': 'https://docs.mermaidchart.com/mermaid-oss/config/theming.html',
|
||||
'config/math.md': 'https://docs.mermaidchart.com/mermaid-oss/config/math.html',
|
||||
'config/accessibility.md': 'https://docs.mermaidchart.com/mermaid-oss/config/accessibility.html',
|
||||
'config/mermaidCLI.md': 'https://docs.mermaidchart.com/mermaid-oss/config/mermaidCLI.html',
|
||||
'config/faq.md': 'https://docs.mermaidchart.com/mermaid-oss/config/faq.html',
|
||||
|
||||
// Ecosystem section
|
||||
'ecosystem/mermaid-chart.md':
|
||||
'https://docs.mermaidchart.com/mermaid-oss/ecosystem/mermaid-chart.html',
|
||||
'ecosystem/tutorials.md': 'https://docs.mermaidchart.com/mermaid-oss/ecosystem/tutorials.html',
|
||||
'ecosystem/integrations-community.md':
|
||||
'https://docs.mermaidchart.com/mermaid-oss/ecosystem/integrations-community.html',
|
||||
'ecosystem/integrations-create.md':
|
||||
'https://docs.mermaidchart.com/mermaid-oss/ecosystem/integrations-create.html',
|
||||
|
||||
// Community section
|
||||
'community/intro.md': 'https://docs.mermaidchart.com/mermaid-oss/community/intro.html',
|
||||
'community/contributing.md':
|
||||
'https://docs.mermaidchart.com/mermaid-oss/community/contributing.html',
|
||||
'community/new-diagram.md':
|
||||
'https://docs.mermaidchart.com/mermaid-oss/community/new-diagram.html',
|
||||
'community/questions-and-suggestions.md':
|
||||
'https://docs.mermaidchart.com/mermaid-oss/community/questions-and-suggestions.html',
|
||||
'community/security.md': 'https://docs.mermaidchart.com/mermaid-oss/community/security.html',
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function to get canonical URL for a specific page
|
||||
* This can be used in frontmatter or for manual overrides
|
||||
*/
|
||||
export function getCanonicalUrl(relativePath: string): string | undefined {
|
||||
return `https://mermaid.ai/open-source/${relativePath}`;
|
||||
return specificCanonicalUrls[relativePath];
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { PageData } from 'vitepress';
|
||||
import { canonicalConfig } from './canonical-config.js';
|
||||
import { canonicalConfig, specificCanonicalUrls } from './canonical-config.js';
|
||||
|
||||
/**
|
||||
* Configuration for canonical URL generation
|
||||
@@ -48,15 +48,31 @@ const defaultConfig: CanonicalUrlConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if a path matches any of the exclude patterns
|
||||
*/
|
||||
function shouldExcludePath(relativePath: string, excludePatterns: string[] = []): boolean {
|
||||
return excludePatterns.some((pattern) => {
|
||||
// Convert glob pattern to regex
|
||||
const regexPattern = pattern
|
||||
.replace(/\*\*/g, '.*')
|
||||
.replace(/\*/g, '[^/]*')
|
||||
.replace(/\?/g, '.')
|
||||
.replace(/\./g, '\\.');
|
||||
const regex = new RegExp(`^${regexPattern}$`);
|
||||
return regex.test(relativePath);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform a relative path to a canonical URL path
|
||||
*/
|
||||
export function transformPath(relativePath: string, config: CanonicalUrlConfig): string {
|
||||
function transformPath(relativePath: string, config: CanonicalUrlConfig): string {
|
||||
let transformedPath = relativePath;
|
||||
|
||||
// Apply built-in transformations
|
||||
if (config.transformations?.removeMarkdownExtension) {
|
||||
transformedPath = transformedPath.replace(/\.md$/, '.html');
|
||||
transformedPath = transformedPath.replace(/\.md$/, '');
|
||||
}
|
||||
|
||||
if (config.transformations?.removeIndex) {
|
||||
@@ -100,9 +116,45 @@ function generateCanonicalUrl(relativePath: string, config: CanonicalUrlConfig):
|
||||
export function addCanonicalUrls(pageData: PageData): void {
|
||||
const config = canonicalConfig;
|
||||
|
||||
// Check for specific canonical URLs first
|
||||
const specificUrl = specificCanonicalUrls[pageData.relativePath];
|
||||
if (specificUrl) {
|
||||
addCanonicalToHead(pageData, specificUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip if canonical URL is already explicitly set in frontmatter
|
||||
if (pageData.frontmatter.canonical) {
|
||||
// If it's already a full URL, use as-is
|
||||
if (pageData.frontmatter.canonical.startsWith('http')) {
|
||||
addCanonicalToHead(pageData, pageData.frontmatter.canonical);
|
||||
return;
|
||||
}
|
||||
// If it's a relative path, convert to absolute URL
|
||||
const canonicalUrl = config.baseUrl + pageData.frontmatter.canonical;
|
||||
addCanonicalToHead(pageData, canonicalUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip if canonicalPath is set in frontmatter
|
||||
if (pageData.frontmatter.canonicalPath) {
|
||||
const canonicalUrl = config.baseUrl + pageData.frontmatter.canonicalPath;
|
||||
addCanonicalToHead(pageData, canonicalUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip if auto-generation is disabled
|
||||
if (!config.autoGenerate) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip if path should be excluded
|
||||
if (shouldExcludePath(pageData.relativePath, config.excludePatterns)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate canonical URL
|
||||
const canonicalUrl = generateCanonicalUrl(pageData.relativePath, config);
|
||||
transformPath(pageData.relativePath, config);
|
||||
addCanonicalToHead(pageData, canonicalUrl);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ function applyStyle(dom, styleFn) {
|
||||
}
|
||||
}
|
||||
|
||||
async function addHtmlSpan(
|
||||
export async function addHtmlSpan(
|
||||
element,
|
||||
node,
|
||||
width,
|
||||
|
||||
@@ -1,56 +1,9 @@
|
||||
import { select } from 'd3';
|
||||
import { getConfig } from '../../diagram-api/diagramAPI.js';
|
||||
import common, {
|
||||
evaluate,
|
||||
hasKatex,
|
||||
renderKatexSanitized,
|
||||
sanitizeText,
|
||||
} from '../../diagrams/common/common.js';
|
||||
import { evaluate } from '../../diagrams/common/common.js';
|
||||
import { log } from '../../logger.js';
|
||||
import { decodeEntities } from '../../utils.js';
|
||||
|
||||
/**
|
||||
* @param dom
|
||||
* @param styleFn
|
||||
*/
|
||||
function applyStyle(dom, styleFn) {
|
||||
if (styleFn) {
|
||||
dom.attr('style', styleFn);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} node
|
||||
* @returns {Promise<SVGForeignObjectElement>} Node
|
||||
*/
|
||||
async function addHtmlLabel(node) {
|
||||
const fo = select(document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject'));
|
||||
const div = fo.append('xhtml:div');
|
||||
|
||||
const config = getConfig();
|
||||
let label = node.label;
|
||||
if (node.label && hasKatex(node.label)) {
|
||||
label = await renderKatexSanitized(node.label.replace(common.lineBreakRegex, '\n'), config);
|
||||
}
|
||||
const labelClass = node.isNode ? 'nodeLabel' : 'edgeLabel';
|
||||
const labelSpan =
|
||||
'<span class="' +
|
||||
labelClass +
|
||||
'" ' +
|
||||
(node.labelStyle ? 'style="' + node.labelStyle + '"' : '') + // codeql [js/html-constructed-from-input] : false positive
|
||||
'>' +
|
||||
label +
|
||||
'</span>';
|
||||
div.html(sanitizeText(labelSpan, config));
|
||||
|
||||
applyStyle(div, node.labelStyle);
|
||||
div.style('display', 'inline-block');
|
||||
div.style('padding-right', '1px');
|
||||
// Fix for firefox
|
||||
div.style('white-space', 'nowrap');
|
||||
div.attr('xmlns', 'http://www.w3.org/1999/xhtml');
|
||||
return fo.node();
|
||||
}
|
||||
import { addHtmlSpan } from '../createText.js';
|
||||
/**
|
||||
* @param _vertexText
|
||||
* @param style
|
||||
@@ -65,7 +18,6 @@ const createLabel = async (_vertexText, style, isTitle, isNode) => {
|
||||
}
|
||||
|
||||
if (evaluate(getConfig().flowchart.htmlLabels)) {
|
||||
// TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that?
|
||||
vertexText = vertexText.replace(/\\n|\n/g, '<br />');
|
||||
log.info('vertexText' + vertexText);
|
||||
const node = {
|
||||
@@ -76,8 +28,10 @@ const createLabel = async (_vertexText, style, isTitle, isNode) => {
|
||||
),
|
||||
labelStyle: style ? style.replace('fill:', 'color:') : style,
|
||||
};
|
||||
let vertexNode = await addHtmlLabel(node);
|
||||
// vertexNode.parentNode.removeChild(vertexNode);
|
||||
const config = getConfig();
|
||||
const width = config.flowchart?.wrappingWidth || 200;
|
||||
const tempContainer = select(document.createElementNS('http://www.w3.org/2000/svg', 'g'));
|
||||
const vertexNode = await addHtmlSpan(tempContainer, node, width, '', false, config);
|
||||
return vertexNode;
|
||||
} else {
|
||||
const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
|
||||
Reference in New Issue
Block a user