chore:little fixes and formating and linting and patches
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import fs from 'node:fs';
|
||||
import { join, resolve } from 'node:path';
|
||||
import { dirname } from 'node:path';
|
||||
import { dirname, join, resolve } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
@@ -11,9 +10,29 @@ import type { PackageInfo } from './publish';
|
||||
const workspacePath = (relativePath: string) =>
|
||||
resolve(__dirname, '../../', relativePath);
|
||||
|
||||
// Pre-compiled regex patterns for performance
|
||||
const INDENT_REGEX = /^(\s*)/;
|
||||
const FRONTMATTER_REGEX = /^---\n([\s\S]*?)\n---\n/;
|
||||
const FRONTMATTER_REPLACE_REGEX = /^---\n[\s\S]*?\n---\n/;
|
||||
const TITLE_REGEX = /^title:\s*(.+)$/m;
|
||||
const DESCRIPTION_REGEX = /^description:\s*(.+)$/m;
|
||||
const COMMON_SDK_CONFIG_REGEX = /<CommonSdkConfig\s*\/>/g;
|
||||
const WEB_SDK_CONFIG_REGEX = /<WebSdkConfig\s*\/>/g;
|
||||
const CODE_BLOCK_REGEX = /```[\s\S]*?```/g;
|
||||
const IMPORT_STATEMENT_REGEX = /^import\s+.*$/gm;
|
||||
const TABS_ITEMS_REGEX = /<Tabs\s+items=\{([^}]+)\}>/;
|
||||
const TAB_VALUE_REGEX = /<Tab\s+value="([^"]+)">([\s\S]*?)<\/Tab>/g;
|
||||
const TABS_WRAPPER_REGEX = /<Tabs[^>]*>([\s\S]*?)<\/Tabs>/g;
|
||||
const SELF_CLOSING_JSX_REGEX = /<[A-Z][a-zA-Z]*[^>]*\/>/g;
|
||||
const JSX_COMPONENT_REGEX = /<([A-Z][a-zA-Z]*)[^>]*>([\s\S]*?)<\/\1>/g;
|
||||
const REMAINING_JSX_REGEX = /<\/?[A-Z][a-zA-Z]*[^>]*>/g;
|
||||
const QUOTE_REGEX = /['"]/g;
|
||||
|
||||
const dedentContent = (text: string): string => {
|
||||
const lines = text.split('\n');
|
||||
if (lines.length === 0) return text;
|
||||
if (lines.length === 0) {
|
||||
return text;
|
||||
}
|
||||
|
||||
// Find the minimum indentation (excluding empty lines)
|
||||
// We'll dedent code blocks too, so include them in the calculation
|
||||
@@ -21,19 +40,27 @@ const dedentContent = (text: string): string => {
|
||||
for (const line of lines) {
|
||||
const trimmed = line.trim();
|
||||
// Skip empty lines
|
||||
if (trimmed.length === 0) continue;
|
||||
const indent = line.match(/^(\s*)/)?.[1]?.length ?? 0;
|
||||
if (indent < minIndent) minIndent = indent;
|
||||
if (trimmed.length === 0) {
|
||||
continue;
|
||||
}
|
||||
const indent = line.match(INDENT_REGEX)?.[1]?.length ?? 0;
|
||||
if (indent < minIndent) {
|
||||
minIndent = indent;
|
||||
}
|
||||
}
|
||||
|
||||
// If no indentation found, return as-is
|
||||
if (minIndent === Number.POSITIVE_INFINITY || minIndent === 0) return text;
|
||||
if (minIndent === Number.POSITIVE_INFINITY || minIndent === 0) {
|
||||
return text;
|
||||
}
|
||||
|
||||
// Remove the common indentation from all lines
|
||||
return lines
|
||||
.map((line) => {
|
||||
// For lines shorter than minIndent, just return them as-is (preserves empty lines)
|
||||
if (line.length < minIndent) return line;
|
||||
if (line.length < minIndent) {
|
||||
return line;
|
||||
}
|
||||
// Remove the common indentation
|
||||
const dedented = line.slice(minIndent);
|
||||
// If the line was all whitespace, return empty string to preserve the line
|
||||
@@ -44,16 +71,16 @@ const dedentContent = (text: string): string => {
|
||||
|
||||
const transformMdxToReadme = (
|
||||
mdxContent: string,
|
||||
packageName: string,
|
||||
packageName: string
|
||||
): string => {
|
||||
let content = mdxContent;
|
||||
|
||||
// Load MDX component content files
|
||||
const commonSdkConfigPath = workspacePath(
|
||||
'apps/public/src/components/common-sdk-config.mdx',
|
||||
'apps/public/src/components/common-sdk-config.mdx'
|
||||
);
|
||||
const webSdkConfigPath = workspacePath(
|
||||
'apps/public/src/components/web-sdk-config.mdx',
|
||||
'apps/public/src/components/web-sdk-config.mdx'
|
||||
);
|
||||
|
||||
let commonSdkConfigContent = '';
|
||||
@@ -76,59 +103,60 @@ const transformMdxToReadme = (
|
||||
}
|
||||
|
||||
// Extract title from frontmatter
|
||||
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---\n/);
|
||||
const frontmatterMatch = content.match(FRONTMATTER_REGEX);
|
||||
let title = packageName;
|
||||
let description = '';
|
||||
|
||||
if (frontmatterMatch?.[1]) {
|
||||
const frontmatter = frontmatterMatch[1];
|
||||
const titleMatch = frontmatter.match(/^title:\s*(.+)$/m);
|
||||
const descMatch = frontmatter.match(/^description:\s*(.+)$/m);
|
||||
if (titleMatch?.[1]) title = titleMatch[1].trim();
|
||||
if (descMatch?.[1]) description = descMatch[1].trim();
|
||||
const titleMatch = frontmatter.match(TITLE_REGEX);
|
||||
const descMatch = frontmatter.match(DESCRIPTION_REGEX);
|
||||
if (titleMatch?.[1]) {
|
||||
title = titleMatch[1].trim();
|
||||
}
|
||||
if (descMatch?.[1]) {
|
||||
description = descMatch[1].trim();
|
||||
}
|
||||
|
||||
// Remove frontmatter
|
||||
content = content.replace(/^---\n[\s\S]*?\n---\n/, '');
|
||||
content = content.replace(FRONTMATTER_REPLACE_REGEX, '');
|
||||
}
|
||||
|
||||
// Replace MDX component references with their actual content
|
||||
// This must happen before code block protection so component content is also protected
|
||||
if (commonSdkConfigContent) {
|
||||
content = content.replace(
|
||||
/<CommonSdkConfig\s*\/>/g,
|
||||
`\n${commonSdkConfigContent}\n`,
|
||||
COMMON_SDK_CONFIG_REGEX,
|
||||
`\n${commonSdkConfigContent}\n`
|
||||
);
|
||||
}
|
||||
if (webSdkConfigContent) {
|
||||
content = content.replace(
|
||||
/<WebSdkConfig\s*\/>/g,
|
||||
`\n${webSdkConfigContent}\n`,
|
||||
WEB_SDK_CONFIG_REGEX,
|
||||
`\n${webSdkConfigContent}\n`
|
||||
);
|
||||
}
|
||||
|
||||
// Protect code blocks from transformation
|
||||
// Extract code blocks before any transformations to preserve their content
|
||||
const codeBlockPlaceholders: string[] = [];
|
||||
// Match code blocks: ```language (optional) followed by content until closing ```
|
||||
// Using [\s\S] to match across newlines, non-greedy to stop at first closing ```
|
||||
const codeBlockRegex = /```[\s\S]*?```/g;
|
||||
|
||||
// Extract and replace code blocks with placeholders
|
||||
content = content.replace(codeBlockRegex, (match) => {
|
||||
content = content.replace(CODE_BLOCK_REGEX, (match) => {
|
||||
const placeholder = `__CODE_BLOCK_${codeBlockPlaceholders.length}__`;
|
||||
codeBlockPlaceholders.push(match);
|
||||
return placeholder;
|
||||
});
|
||||
|
||||
// Remove import statements (outside code blocks)
|
||||
content = content.replace(/^import\s+.*$/gm, '');
|
||||
content = content.replace(IMPORT_STATEMENT_REGEX, '');
|
||||
|
||||
// Handle Tabs component specially - convert to markdown sections
|
||||
// Extract tabs items from items prop
|
||||
const tabsItemsMatch = content.match(/<Tabs\s+items=\{([^\}]+)\}>/);
|
||||
const tabsItemsMatch = content.match(TABS_ITEMS_REGEX);
|
||||
const tabsItems = tabsItemsMatch?.[1]
|
||||
? tabsItemsMatch[1]
|
||||
.replace(/['"]/g, '')
|
||||
.replace(QUOTE_REGEX, '')
|
||||
.split(',')
|
||||
.map((item) => item.trim())
|
||||
: [];
|
||||
@@ -136,29 +164,23 @@ const transformMdxToReadme = (
|
||||
// Replace Tabs/Tab structure with markdown sections
|
||||
if (tabsItems.length > 0) {
|
||||
// Match each Tab and convert to a markdown section
|
||||
content = content.replace(
|
||||
/<Tab\s+value="([^"]+)">([\s\S]*?)<\/Tab>/g,
|
||||
(match, value, tabContent) => {
|
||||
const dedented = dedentContent(tabContent).trim();
|
||||
return `\n#### ${value}\n\n${dedented}\n\n`;
|
||||
},
|
||||
);
|
||||
content = content.replace(TAB_VALUE_REGEX, (_match, value, tabContent) => {
|
||||
const dedented = dedentContent(tabContent).trim();
|
||||
return `\n#### ${value}\n\n${dedented}\n\n`;
|
||||
});
|
||||
// Remove the Tabs wrapper
|
||||
content = content.replace(/<Tabs[^>]*>([\s\S]*?)<\/Tabs>/g, '$1');
|
||||
content = content.replace(TABS_WRAPPER_REGEX, '$1');
|
||||
} else {
|
||||
// Fallback: if no items prop, just convert tabs to sections
|
||||
content = content.replace(
|
||||
/<Tab\s+value="([^"]+)">([\s\S]*?)<\/Tab>/g,
|
||||
(match, value, tabContent) => {
|
||||
const dedented = dedentContent(tabContent).trim();
|
||||
return `\n#### ${value}\n\n${dedented}\n\n`;
|
||||
},
|
||||
);
|
||||
content = content.replace(/<Tabs[^>]*>([\s\S]*?)<\/Tabs>/g, '$1');
|
||||
content = content.replace(TAB_VALUE_REGEX, (_match, value, tabContent) => {
|
||||
const dedented = dedentContent(tabContent).trim();
|
||||
return `\n#### ${value}\n\n${dedented}\n\n`;
|
||||
});
|
||||
content = content.replace(TABS_WRAPPER_REGEX, '$1');
|
||||
}
|
||||
|
||||
// Remove self-closing JSX components (like <CommonSdkConfig />, <WebSdkConfig />)
|
||||
content = content.replace(/<[A-Z][a-zA-Z]*[^>]*\/>/g, '');
|
||||
content = content.replace(SELF_CLOSING_JSX_REGEX, '');
|
||||
|
||||
// Remove JSX component tags but preserve content between opening/closing tags
|
||||
// Handle nested components by recursively removing outer tags
|
||||
@@ -168,15 +190,15 @@ const transformMdxToReadme = (
|
||||
previousContent = content;
|
||||
// Match JSX components with their content - handles one level of nesting
|
||||
content = content.replace(
|
||||
/<([A-Z][a-zA-Z]*)[^>]*>([\s\S]*?)<\/\1>/g,
|
||||
(match, tagName, innerContent) => {
|
||||
JSX_COMPONENT_REGEX,
|
||||
(_match, _tagName, innerContent) => {
|
||||
return dedentContent(innerContent).trim();
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Remove any remaining JSX tags (self-closing or unmatched)
|
||||
content = content.replace(/<\/?[A-Z][a-zA-Z]*[^>]*>/g, '');
|
||||
content = content.replace(REMAINING_JSX_REGEX, '');
|
||||
|
||||
// Restore code blocks
|
||||
codeBlockPlaceholders.forEach((codeBlock, index) => {
|
||||
@@ -185,8 +207,8 @@ const transformMdxToReadme = (
|
||||
|
||||
// Convert internal links (starting with /) to absolute URLs
|
||||
content = content.replace(
|
||||
/\[([^\]]+)\]\((\/[^\)]+)\)/g,
|
||||
'[$1](https://openpanel.dev$2)',
|
||||
/\[([^\]]+)\]\((\/[^)]+)\)/g,
|
||||
'[$1](https://openpanel.dev$2)'
|
||||
);
|
||||
|
||||
// Clean up extra blank lines
|
||||
@@ -209,7 +231,7 @@ const transformMdxToReadme = (
|
||||
|
||||
export const generateReadme = (
|
||||
packages: Record<string, PackageInfo>,
|
||||
dependents: string[],
|
||||
dependents: string[]
|
||||
): string[] => {
|
||||
const generatedReadmes: string[] = [];
|
||||
for (const dep of dependents) {
|
||||
@@ -217,7 +239,7 @@ export const generateReadme = (
|
||||
const docPath = pkg?.config?.docPath;
|
||||
if (!docPath) {
|
||||
console.log(
|
||||
`📝 Skipping README generation for ${dep} (no docPath configured)`,
|
||||
`📝 Skipping README generation for ${dep} (no docPath configured)`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,11 @@ import { generateReadme } from './generate-readme';
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
// Pre-compiled regex patterns for performance
|
||||
const PRE_RELEASE_SUFFIX_REGEX = /-.*$/;
|
||||
const LOCAL_SUFFIX_REGEX = /-local$/;
|
||||
const WORKSPACE_PREFIX_REGEX = /^workspace:/;
|
||||
|
||||
// Types
|
||||
interface PackageJson {
|
||||
name: string;
|
||||
@@ -72,7 +77,7 @@ const getNextVersion = (version: string, type: ReleaseType): string => {
|
||||
throw new Error('Invalid version');
|
||||
}
|
||||
return type.startsWith('pre')
|
||||
? nextVersion.replace(/-.*$/, '-rc')
|
||||
? nextVersion.replace(PRE_RELEASE_SUFFIX_REGEX, '-rc')
|
||||
: nextVersion;
|
||||
};
|
||||
|
||||
@@ -92,7 +97,7 @@ const loadPackages = (
|
||||
const pkgJson = JSON.parse(
|
||||
fs.readFileSync(pkgPath, 'utf-8')
|
||||
) as PackageJson;
|
||||
const version = pkgJson.version.replace(/-local$/, '');
|
||||
const version = pkgJson.version.replace(LOCAL_SUFFIX_REGEX, '');
|
||||
return [
|
||||
pkgJson.name,
|
||||
{
|
||||
@@ -140,8 +145,12 @@ const updatePackageJsonForRelease = (
|
||||
depName,
|
||||
dependents.includes(depName)
|
||||
? packages[depName]?.nextVersion ||
|
||||
depVersion.replace(/-local$/, '').replace(/^workspace:/, '')
|
||||
: depVersion.replace(/-local$/, '').replace(/^workspace:/, ''),
|
||||
depVersion
|
||||
.replace(LOCAL_SUFFIX_REGEX, '')
|
||||
.replace(WORKSPACE_PREFIX_REGEX, '')
|
||||
: depVersion
|
||||
.replace(LOCAL_SUFFIX_REGEX, '')
|
||||
.replace(WORKSPACE_PREFIX_REGEX, ''),
|
||||
]
|
||||
)
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user