Files
mermaid/.esbuild/build.ts
Ashish Jain 39b555cad0 feat: Add comprehensive ANTLR build integration and watch capabilities
�� Major ANTLR System Enhancements:

## New Features:
-  Generic ANTLR generation system (scripts/antlr-generate.mts)
-  Dedicated watch command for grammar development (scripts/antlr-watch.mts)
-  Build pipeline integration with postinstall hooks
-  Development server watch integration for .g4 files
-  Sequence diagram ANTLR parser implementation

## Build Integration:
- 🏗️ Added ANTLR generation to build process (.esbuild/build.ts)
- 📦 Added postinstall hooks to package.json files
- 🔄 Integrated ANTLR generation with dev server (.esbuild/server-antlr.ts)
- 🎯 Smart path detection for root vs package directory execution

## New Commands:
- `pnpm antlr:generate` - Generic generation for all diagrams
- `pnpm antlr:watch` - Grammar development with file watching
- Auto-generation during `pnpm install` and `pnpm build`

## Documentation:
- 📖 Consolidated all ANTLR docs into ANTLR_SETUP.md
- 🗑️ Removed duplicate ANTLR_GENERATION.md
- 📋 Added comprehensive troubleshooting and usage guides
- 🎯 Updated with build integration and watch functionality

## Parser Implementations:
- 🔄 Enhanced sequence diagram ANTLR parser with dual-pattern support
- 🛠️ Added SequenceListener, SequenceVisitor, SequenceParserCore
-  Improved flowchart parser integration and error handling

## Benefits:
- 🔄 Zero manual steps - ANTLR files always generated automatically
-  Fast grammar development with watch mode
- 🎯 Unified workflow for all diagram types
- 🛡️ CI/CD ready with build integration
- 📊 Clear feedback and comprehensive logging

This establishes a complete, production-ready ANTLR development workflow!
2025-09-18 11:22:19 +02:00

127 lines
3.9 KiB
TypeScript

import { build } from 'esbuild';
import { cp, mkdir, readFile, rename, writeFile } from 'node:fs/promises';
import { execSync } from 'child_process';
import { packageOptions } from '../.build/common.js';
import { generateLangium } from '../.build/generateLangium.js';
import type { MermaidBuildOptions } from './util.js';
import { defaultOptions, getBuildConfig } from './util.js';
const shouldVisualize = process.argv.includes('--visualize');
const buildPackage = async (entryName: keyof typeof packageOptions) => {
const commonOptions: MermaidBuildOptions = {
...defaultOptions,
options: packageOptions[entryName],
} as const;
const buildConfigs: MermaidBuildOptions[] = [
// package.mjs
{ ...commonOptions },
// package.min.mjs
{
...commonOptions,
minify: true,
metafile: shouldVisualize,
},
// package.core.mjs
{ ...commonOptions, core: true },
];
if (entryName === 'mermaid') {
const iifeOptions: MermaidBuildOptions = { ...commonOptions, format: 'iife' };
buildConfigs.push(
// mermaid.js
{ ...iifeOptions },
// mermaid.min.js
{ ...iifeOptions, minify: true, metafile: shouldVisualize },
// mermaid.tiny.min.js
{
...iifeOptions,
minify: true,
includeLargeFeatures: false,
metafile: shouldVisualize,
sourcemap: false,
}
);
}
if (entryName === 'mermaid-zenuml') {
const iifeOptions: MermaidBuildOptions = {
...commonOptions,
format: 'iife',
globalName: 'mermaid-zenuml',
};
buildConfigs.push(
// mermaid-zenuml.js
{ ...iifeOptions },
// mermaid-zenuml.min.js
{ ...iifeOptions, minify: true, metafile: shouldVisualize }
);
}
const results = await Promise.all(buildConfigs.map((option) => build(getBuildConfig(option))));
if (shouldVisualize) {
for (const { metafile } of results) {
if (!metafile?.outputs) {
continue;
}
const fileName = Object.keys(metafile.outputs)
.find((file) => !file.includes('chunks') && file.endsWith('js'))!
.replace('dist/', '');
// Upload metafile into https://esbuild.github.io/analyze/
await writeFile(`stats/${fileName}.meta.json`, JSON.stringify(metafile));
}
}
};
const handler = (e) => {
// eslint-disable-next-line no-console
console.error(e);
process.exit(1);
};
const buildTinyMermaid = async () => {
await mkdir('./packages/tiny/dist', { recursive: true });
await rename(
'./packages/mermaid/dist/mermaid.tiny.min.js',
'./packages/tiny/dist/mermaid.tiny.js'
);
// Copy version from mermaid's package.json to tiny's package.json
const mermaidPkg = JSON.parse(await readFile('./packages/mermaid/package.json', 'utf8'));
const tinyPkg = JSON.parse(await readFile('./packages/tiny/package.json', 'utf8'));
tinyPkg.version = mermaidPkg.version;
await writeFile('./packages/tiny/package.json', JSON.stringify(tinyPkg, null, 2) + '\n');
await cp('./packages/mermaid/CHANGELOG.md', './packages/tiny/CHANGELOG.md');
};
/**
* Generate ANTLR parser files from grammar files
*/
const generateAntlr = () => {
try {
// eslint-disable-next-line no-console
console.log('🎯 ANTLR: Generating parser files...');
execSync('tsx scripts/antlr-generate.mts', { stdio: 'inherit' });
// eslint-disable-next-line no-console
console.log('✅ ANTLR: Parser files generated successfully');
} catch (error) {
// eslint-disable-next-line no-console
console.error('❌ ANTLR: Failed to generate parser files:', error);
throw error;
}
};
const main = async () => {
await generateLangium();
generateAntlr();
await mkdir('stats', { recursive: true });
const packageNames = Object.keys(packageOptions) as (keyof typeof packageOptions)[];
// it should build `parser` before `mermaid` because it's a dependency
for (const pkg of packageNames) {
await buildPackage(pkg).catch(handler);
}
await buildTinyMermaid();
};
void main();