mirror of
https://github.com/apache/superset.git
synced 2026-04-07 10:31:50 +00:00
154 lines
4.8 KiB
JavaScript
154 lines
4.8 KiB
JavaScript
/**
|
|
* Licensed to the Apache Software Foundation (ASF) under one
|
|
* or more contributor license agreements. See the NOTICE file
|
|
* distributed with this work for additional information
|
|
* regarding copyright ownership. The ASF licenses this file
|
|
* to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance
|
|
* with the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing,
|
|
* software distributed under the License is distributed on an
|
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
* KIND, either express or implied. See the License for the
|
|
* specific language governing permissions and limitations
|
|
* under the License.
|
|
*/
|
|
|
|
// Note: visit from unist-util-visit is available if needed for tree traversal
|
|
|
|
/**
|
|
* Remark plugin that automatically injects TechArticle schema import and component
|
|
* into documentation MDX files based on frontmatter.
|
|
*
|
|
* This enables rich snippets for technical documentation in search results.
|
|
*
|
|
* Frontmatter options:
|
|
* - title: (required) Article headline
|
|
* - description: (required) Article description
|
|
* - keywords: (optional) Array of keywords
|
|
* - seo_proficiency: (optional) 'Beginner' or 'Expert', defaults to 'Beginner'
|
|
* - seo_schema: (optional) Set to false to disable schema injection
|
|
*/
|
|
export default function remarkTechArticleSchema() {
|
|
return (tree, file) => {
|
|
const frontmatter = file.data.frontMatter || {};
|
|
|
|
// Skip if explicitly disabled or missing required fields
|
|
if (frontmatter.seo_schema === false) {
|
|
return;
|
|
}
|
|
|
|
// Only add schema if we have title and description
|
|
if (!frontmatter.title || !frontmatter.description) {
|
|
return;
|
|
}
|
|
|
|
const title = frontmatter.title;
|
|
const description = frontmatter.description;
|
|
const keywords = Array.isArray(frontmatter.keywords) ? frontmatter.keywords : [];
|
|
const proficiencyLevel = frontmatter.seo_proficiency || 'Beginner';
|
|
|
|
// Create the import statement
|
|
const importNode = {
|
|
type: 'mdxjsEsm',
|
|
value: `import TechArticleSchema from '@site/src/components/TechArticleSchema';`,
|
|
data: {
|
|
estree: {
|
|
type: 'Program',
|
|
sourceType: 'module',
|
|
body: [
|
|
{
|
|
type: 'ImportDeclaration',
|
|
specifiers: [
|
|
{
|
|
type: 'ImportDefaultSpecifier',
|
|
local: { type: 'Identifier', name: 'TechArticleSchema' },
|
|
},
|
|
],
|
|
source: {
|
|
type: 'Literal',
|
|
value: '@site/src/components/TechArticleSchema',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
},
|
|
};
|
|
|
|
// Create the component node for MDX
|
|
const componentNode = {
|
|
type: 'mdxJsxFlowElement',
|
|
name: 'TechArticleSchema',
|
|
attributes: [
|
|
{
|
|
type: 'mdxJsxAttribute',
|
|
name: 'title',
|
|
value: title,
|
|
},
|
|
{
|
|
type: 'mdxJsxAttribute',
|
|
name: 'description',
|
|
value: description,
|
|
},
|
|
...(keywords.length > 0
|
|
? [
|
|
{
|
|
type: 'mdxJsxAttribute',
|
|
name: 'keywords',
|
|
value: {
|
|
type: 'mdxJsxAttributeValueExpression',
|
|
value: JSON.stringify(keywords),
|
|
data: {
|
|
estree: {
|
|
type: 'Program',
|
|
sourceType: 'module',
|
|
body: [
|
|
{
|
|
type: 'ExpressionStatement',
|
|
expression: {
|
|
type: 'ArrayExpression',
|
|
elements: keywords.map((k) => ({
|
|
type: 'Literal',
|
|
value: k,
|
|
})),
|
|
},
|
|
},
|
|
],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
]
|
|
: []),
|
|
...(proficiencyLevel !== 'Beginner'
|
|
? [
|
|
{
|
|
type: 'mdxJsxAttribute',
|
|
name: 'proficiencyLevel',
|
|
value: proficiencyLevel,
|
|
},
|
|
]
|
|
: []),
|
|
],
|
|
children: [],
|
|
};
|
|
|
|
// Insert import at the beginning
|
|
tree.children.unshift(importNode);
|
|
|
|
// Find the first heading and insert component after it
|
|
let insertIndex = 1; // Default: after import
|
|
for (let i = 1; i < tree.children.length; i++) {
|
|
if (tree.children[i].type === 'heading') {
|
|
insertIndex = i + 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
tree.children.splice(insertIndex, 0, componentNode);
|
|
};
|
|
}
|