Merge branch 'develop' into sidv/tinyMermaid

* develop: (31 commits)
  make LLM integrations a new headline
  build docs
  ci(e2e): avoid commenting on PRs in CI
  chore: Remove unused imports in block
  Fix spelling
  Update docs
  Lychee ignore chrome webstore
  Update link
  chore(deps): update all patch dependencies
  build(docs): vendor CSS dependencies
  chore(deps): update all minor dependencies
  fix linting issues
  Ran lint:fix
  Fix chrome webstore url causing 404
  Add LLM integration section in productivity tools and add HueHive
  build(deps): update `langium` to `v3` and apply the required changes
  Remove dummy change from e2e.yml
  Remove dummy change
  Remove log
  Format message
  ...
This commit is contained in:
Sidharth Vinod
2024-03-08 19:43:56 +05:30
20 changed files with 2419 additions and 2704 deletions

5
.github/lychee.toml vendored
View File

@@ -38,7 +38,10 @@ exclude = [
"https://discord.gg",
# BundlePhobia has frequent downtime
"https://bundlephobia.com"
"https://bundlephobia.com",
# Chrome webstore redirect issue
"https://chromewebstore.google.com"
]
# Exclude all private IPs from checking.

View File

@@ -48,11 +48,26 @@ jobs:
with:
ref: ${{ env.targetHash }}
- name: Install dependencies
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
uses: cypress-io/github-action@v6
with:
# just perform install
runTests: false
- name: Calculate bundle size
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true'}}
run: |
pnpm run build:viz
mkdir -p cypress/snapshots/stats/base
mv stats cypress/snapshots/stats/base
- name: Cypress run
uses: cypress-io/github-action@v4
uses: cypress-io/github-action@v6
id: cypress-snapshot-gen
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
with:
install: false
start: pnpm run dev
wait-on: 'http://localhost:9000'
browser: chrome
@@ -86,15 +101,30 @@ jobs:
path: ./cypress/snapshots
key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
- name: Install dependencies
uses: cypress-io/github-action@v6
with:
runTests: false
- name: Output size diff
if: ${{ matrix.containers == 1 }}
run: |
pnpm run build:viz
mv stats cypress/snapshots/stats/head
echo '## Bundle size difference' >> "$GITHUB_STEP_SUMMARY"
echo '' >> "$GITHUB_STEP_SUMMARY"
npx tsx scripts/size.ts >> "$GITHUB_STEP_SUMMARY"
# Install NPM dependencies, cache them correctly
# and run all Cypress tests
- name: Cypress run
uses: cypress-io/github-action@v4
uses: cypress-io/github-action@v6
id: cypress
# If CYPRESS_RECORD_KEY is set, run in parallel on all containers
# Otherwise (e.g. if running from fork), we run on a single container only
if: ${{ ( env.CYPRESS_RECORD_KEY != '' ) || ( matrix.containers == 1 ) }}
with:
install: false
start: pnpm run dev:coverage
wait-on: 'http://localhost:9000'
browser: chrome

View File

@@ -1,2 +1,2 @@
FROM node:20.11.0-alpine3.19 AS base
FROM node:20.11.1-alpine3.19 AS base
RUN wget -qO- https://get.pnpm.io/install.sh | ENV="$HOME/.shrc" SHELL="$(which sh)" sh -

View File

@@ -14,10 +14,6 @@
`Optional` **bindFunctions**: (`element`: `Element`) => `void`
#### Type declaration
▸ (`element`): `void`
Bind function to be called after the svg has been inserted into the DOM.
This is necessary for adding event listeners to the elements in the svg.
@@ -27,6 +23,10 @@ div.innerHTML = svg;
bindFunctions?.(div); // To call bindFunctions only if it's present.
```
#### Type declaration
▸ (`element`): `void`
##### Parameters
| Name | Type |

View File

@@ -71,6 +71,12 @@ To add an integration to this list, see the [Integrations - create page](./integ
- [redmine-mermaid](https://github.com/styz/redmine_mermaid)
- Visual Studio Code [Polyglot Interactive Notebooks](https://github.com/dotnet/interactive#net-interactive)
### LLM integrations
LLM integrations to create mermaid diagrams using AI from text descriptions.
- [HueHive - Create mermaid diagrams with text](https://huehive.co/tools/diagrams)
### CRM/ERP
Customer Relationship Management/Enterprise Resource Planning
@@ -222,7 +228,7 @@ Communication tools and platforms
| GitHub + Mermaid | - | [🦊🔗](https://addons.mozilla.org/firefox/addon/github-mermaid/) | - | - | [🐙🔗](https://github.com/BackMarket/github-mermaid-extension) |
| Asciidoctor Live Preview | [🎡🔗](https://chromewebstore.google.com/detail/asciidoctorjs-live-previe/iaalpfgpbocpdfblpnhhgllgbdbchmia) | - | - | [🌀🔗](https://microsoftedge.microsoft.com/addons/detail/asciidoctorjs-live-previ/pefkelkanablhjdekgdahplkccnbdggd?hl=en-US) | - |
| Diagram Tab | - | - | - | - | [🐙🔗](https://github.com/khafast/diagramtab) |
| Markdown Diagrams | [🎡🔗](https://chromewebstore.google.com/detail/markdown-diagrams/pmoglnmodacnbbofbgcagndelmgaclel/) | [🦊🔗](https://addons.mozilla.org/en-US/firefox/addon/markdown-diagrams/) | [🔴🔗](https://addons.opera.com/en/extensions/details/markdown-diagrams/) | [🌀🔗](https://microsoftedge.microsoft.com/addons/detail/markdown-diagrams/hceenoomhhdkjjijnmlclkpenkapfihe) | [🐙🔗](https://github.com/marcozaccari/markdown-diagrams-browser-extension/tree/master/doc/examples) |
| Markdown Diagrams | [🎡🔗](https://chromewebstore.google.com/detail/markdown-diagrams/pmoglnmodacnbbofbgcagndelmgaclel) | [🦊🔗](https://addons.mozilla.org/en-US/firefox/addon/markdown-diagrams/) | [🔴🔗](https://addons.opera.com/en/extensions/details/markdown-diagrams/) | [🌀🔗](https://microsoftedge.microsoft.com/addons/detail/markdown-diagrams/hceenoomhhdkjjijnmlclkpenkapfihe) | [🐙🔗](https://github.com/marcozaccari/markdown-diagrams-browser-extension/tree/master/doc/examples) |
| Markdown Viewer | - | [🦊🔗](https://addons.mozilla.org/en-US/firefox/addon/markdown-viewer-chrome/) | - | - | [🐙🔗](https://github.com/simov/markdown-viewer) |
| Extensions for Mermaid | - | - | [🔴🔗](https://addons.opera.com/en/extensions/details/extensions-for-mermaid/) | - | [🐙🔗](https://github.com/Stefan-S/mermaid-extension) |
| Chrome Diagrammer | [🎡🔗](https://chromewebstore.google.com/detail/chrome-diagrammer/bkpbgjmkomfoakfklcjeoegkklgjnnpk) | - | - | - | - |
@@ -252,4 +258,4 @@ Communication tools and platforms
- [mermaid-isomorphic](https://github.com/remcohaszing/mermaid-isomorphic)
- [mermaid-server: Generate diagrams using a HTTP request](https://github.com/TomWright/mermaid-server)
<!--- cspell:ignore Blazorade --->
<!--- cspell:ignore Blazorade HueHive --->

View File

@@ -4,7 +4,7 @@
"version": "10.2.4",
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
"type": "module",
"packageManager": "pnpm@8.15.1",
"packageManager": "pnpm@8.15.4",
"keywords": [
"diagram",
"markdown",
@@ -109,8 +109,9 @@
"jison": "^0.4.18",
"js-yaml": "^4.1.0",
"jsdom": "^22.0.0",
"langium-cli": "2.1.0",
"langium-cli": "3.0.1",
"lint-staged": "^13.2.1",
"markdown-table": "^3.0.3",
"nyc": "^15.1.0",
"path-browserify": "^1.0.1",
"pnpm": "^8.6.8",

View File

@@ -1,9 +1,9 @@
import type { DiagramDB } from '../../diagram-api/types.js';
import type { BlockConfig, BlockType, Block, ClassDef } from './blockTypes.js';
import * as configApi from '../../config.js';
import { clear as commonClear } from '../common/commonDb.js';
import { log } from '../../logger.js';
import clone from 'lodash-es/clone.js';
import * as configApi from '../../config.js';
import type { DiagramDB } from '../../diagram-api/types.js';
import { log } from '../../logger.js';
import { clear as commonClear } from '../common/commonDb.js';
import type { Block, ClassDef } from './blockTypes.js';
// Initialize the node database for simple lookups
let blockDatabase: Record<string, Block> = {};

View File

@@ -1,19 +1,17 @@
import type { Diagram } from '../../Diagram.js';
import * as configApi from '../../config.js';
import { calculateBlockSizes, insertBlocks, insertEdges } from './renderHelpers.js';
import { layout } from './layout.js';
import type { MermaidConfig, BaseDiagramConfig } from '../../config.type.js';
import insertMarkers from '../../dagre-wrapper/markers.js';
import {
select as d3select,
scaleOrdinal as d3scaleOrdinal,
schemeTableau10 as d3schemeTableau10,
select as d3select,
} from 'd3';
import type { ContainerElement } from 'd3';
import type { Diagram } from '../../Diagram.js';
import * as configApi from '../../config.js';
import type { MermaidConfig } from '../../config.type.js';
import insertMarkers from '../../dagre-wrapper/markers.js';
import { log } from '../../logger.js';
import type { BlockDB } from './blockDB.js';
import type { Block } from './blockTypes.js';
import { configureSvgSize } from '../../setupGraphViewbox.js';
import type { BlockDB } from './blockDB.js';
import { layout } from './layout.js';
import { calculateBlockSizes, insertBlocks, insertEdges } from './renderHelpers.js';
/**
* Returns the all the styles from classDef statements in the graph definition.

View File

@@ -1,15 +1,10 @@
import { getStylesFromArray } from '../../utils.js';
import { insertNode, positionNode } from '../../dagre-wrapper/nodes.js';
import { insertEdge, insertEdgeLabel, positionEdgeLabel } from '../../dagre-wrapper/edges.js';
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
import { getConfig } from '../../config.js';
import type { ContainerElement } from 'd3';
import type { Block } from './blockTypes.js';
import { insertEdge, insertEdgeLabel, positionEdgeLabel } from '../../dagre-wrapper/edges.js';
import { insertNode, positionNode } from '../../dagre-wrapper/nodes.js';
import { getStylesFromArray } from '../../utils.js';
import type { BlockDB } from './blockDB.js';
interface Node {
classes: string;
}
import type { Block } from './blockTypes.js';
function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
const vertex = block;

View File

@@ -4,7 +4,7 @@
>
<p class="flex-grow text-center tracking-wide text-text">
<a
href="https://www.mermaidchart.com/app/user/billing/checkout"
href="https://www.mermaidchart.com/app/landing"
target="_blank"
class="unstyled flex-grow tracking-wide plausible-event-name=bannerClick"
>

View File

@@ -1,5 +1,5 @@
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');
@import url('https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css');
@import 'font-awesome/css/font-awesome.min.css';
@import '@mdi/font/css/materialdesignicons.min.css';
:root {
--vp-c-brand: #ff3670;

View File

@@ -66,6 +66,12 @@ To add an integration to this list, see the [Integrations - create page](./integ
- [redmine-mermaid](https://github.com/styz/redmine_mermaid)
- Visual Studio Code [Polyglot Interactive Notebooks](https://github.com/dotnet/interactive#net-interactive)
### LLM integrations
LLM integrations to create mermaid diagrams using AI from text descriptions.
- [HueHive - Create mermaid diagrams with text](https://huehive.co/tools/diagrams)
### CRM/ERP
Customer Relationship Management/Enterprise Resource Planning
@@ -217,7 +223,7 @@ Communication tools and platforms
| GitHub + Mermaid | - | [🦊🔗](https://addons.mozilla.org/firefox/addon/github-mermaid/) | - | - | [🐙🔗](https://github.com/BackMarket/github-mermaid-extension) |
| Asciidoctor Live Preview | [🎡🔗](https://chromewebstore.google.com/detail/asciidoctorjs-live-previe/iaalpfgpbocpdfblpnhhgllgbdbchmia) | - | - | [🌀🔗](https://microsoftedge.microsoft.com/addons/detail/asciidoctorjs-live-previ/pefkelkanablhjdekgdahplkccnbdggd?hl=en-US) | - |
| Diagram Tab | - | - | - | - | [🐙🔗](https://github.com/khafast/diagramtab) |
| Markdown Diagrams | [🎡🔗](https://chromewebstore.google.com/detail/markdown-diagrams/pmoglnmodacnbbofbgcagndelmgaclel/) | [🦊🔗](https://addons.mozilla.org/en-US/firefox/addon/markdown-diagrams/) | [🔴🔗](https://addons.opera.com/en/extensions/details/markdown-diagrams/) | [🌀🔗](https://microsoftedge.microsoft.com/addons/detail/markdown-diagrams/hceenoomhhdkjjijnmlclkpenkapfihe) | [🐙🔗](https://github.com/marcozaccari/markdown-diagrams-browser-extension/tree/master/doc/examples) |
| Markdown Diagrams | [🎡🔗](https://chromewebstore.google.com/detail/markdown-diagrams/pmoglnmodacnbbofbgcagndelmgaclel) | [🦊🔗](https://addons.mozilla.org/en-US/firefox/addon/markdown-diagrams/) | [🔴🔗](https://addons.opera.com/en/extensions/details/markdown-diagrams/) | [🌀🔗](https://microsoftedge.microsoft.com/addons/detail/markdown-diagrams/hceenoomhhdkjjijnmlclkpenkapfihe) | [🐙🔗](https://github.com/marcozaccari/markdown-diagrams-browser-extension/tree/master/doc/examples) |
| Markdown Viewer | - | [🦊🔗](https://addons.mozilla.org/en-US/firefox/addon/markdown-viewer-chrome/) | - | - | [🐙🔗](https://github.com/simov/markdown-viewer) |
| Extensions for Mermaid | - | - | [🔴🔗](https://addons.opera.com/en/extensions/details/extensions-for-mermaid/) | - | [🐙🔗](https://github.com/Stefan-S/mermaid-extension) |
| Chrome Diagrammer | [🎡🔗](https://chromewebstore.google.com/detail/chrome-diagrammer/bkpbgjmkomfoakfklcjeoegkklgjnnpk) | - | - | - | - |
@@ -247,4 +253,4 @@ Communication tools and platforms
- [mermaid-isomorphic](https://github.com/remcohaszing/mermaid-isomorphic)
- [mermaid-server: Generate diagrams using a HTTP request](https://github.com/TomWright/mermaid-server)
<!--- cspell:ignore Blazorade --->
<!--- cspell:ignore Blazorade HueHive --->

View File

@@ -15,7 +15,9 @@
"fetch-contributors": "tsx .vitepress/scripts/fetch-contributors.ts"
},
"dependencies": {
"@mdi/font": "^6.9.96",
"@vueuse/core": "^10.1.0",
"font-awesome": "^4.7.0",
"jiti": "^1.18.2",
"vue": "^3.3",
"mermaid": "workspace:^"
@@ -32,7 +34,7 @@
"unplugin-vue-components": "^0.26.0",
"vite": "^4.5.2",
"vite-plugin-pwa": "^0.19.0",
"vitepress": "1.0.0-rc.42",
"vitepress": "1.0.0-rc.44",
"workbox-window": "^7.0.0"
}
}

View File

@@ -34,7 +34,7 @@
"ast"
],
"dependencies": {
"langium": "2.1.2"
"langium": "3.0.0"
},
"devDependencies": {
"chevrotain": "^11.0.3"

View File

@@ -1,11 +1,16 @@
import type {
DefaultSharedModuleContext,
LangiumServices,
LangiumSharedServices,
DefaultSharedCoreModuleContext,
LangiumCoreServices,
LangiumSharedCoreServices,
Module,
PartialLangiumServices,
PartialLangiumCoreServices,
} from 'langium';
import {
EmptyFileSystem,
createDefaultCoreModule,
createDefaultSharedCoreModule,
inject,
} from 'langium';
import { EmptyFileSystem, createDefaultModule, createDefaultSharedModule, inject } from 'langium';
import { CommonValueConverter } from '../common/index.js';
import { InfoGeneratedModule, MermaidGeneratedSharedModule } from '../generated/module.js';
@@ -24,13 +29,13 @@ type InfoAddedServices = {
/**
* Union of Langium default services and `Info` services.
*/
export type InfoServices = LangiumServices & InfoAddedServices;
export type InfoServices = LangiumCoreServices & InfoAddedServices;
/**
* Dependency injection module that overrides Langium default services and
* contributes the declared `Info` services.
*/
export const InfoModule: Module<InfoServices, PartialLangiumServices & InfoAddedServices> = {
export const InfoModule: Module<InfoServices, PartialLangiumCoreServices & InfoAddedServices> = {
parser: {
TokenBuilder: () => new InfoTokenBuilder(),
ValueConverter: () => new CommonValueConverter(),
@@ -51,16 +56,16 @@ export const InfoModule: Module<InfoServices, PartialLangiumServices & InfoAdded
* @param context - Optional module context with the LSP connection
* @returns An object wrapping the shared services and the language-specific services
*/
export function createInfoServices(context: DefaultSharedModuleContext = EmptyFileSystem): {
shared: LangiumSharedServices;
export function createInfoServices(context: DefaultSharedCoreModuleContext = EmptyFileSystem): {
shared: LangiumSharedCoreServices;
Info: InfoServices;
} {
const shared: LangiumSharedServices = inject(
createDefaultSharedModule(context),
const shared: LangiumSharedCoreServices = inject(
createDefaultSharedCoreModule(context),
MermaidGeneratedSharedModule
);
const Info: InfoServices = inject(
createDefaultModule({ shared }),
createDefaultCoreModule({ shared }),
InfoGeneratedModule,
InfoModule
);

View File

@@ -1,11 +1,17 @@
import type {
DefaultSharedModuleContext,
LangiumServices,
LangiumSharedServices,
DefaultSharedCoreModuleContext,
LangiumCoreServices,
LangiumSharedCoreServices,
Module,
PartialLangiumServices,
PartialLangiumCoreServices,
} from 'langium';
import { EmptyFileSystem, createDefaultModule, createDefaultSharedModule, inject } from 'langium';
import {
EmptyFileSystem,
createDefaultCoreModule,
createDefaultSharedCoreModule,
inject,
} from 'langium';
import { CommonValueConverter } from '../common/valueConverter.js';
import { MermaidGeneratedSharedModule, PacketGeneratedModule } from '../generated/module.js';
import { PacketTokenBuilder } from './tokenBuilder.js';
@@ -23,13 +29,16 @@ type PacketAddedServices = {
/**
* Union of Langium default services and `Packet` services.
*/
export type PacketServices = LangiumServices & PacketAddedServices;
export type PacketServices = LangiumCoreServices & PacketAddedServices;
/**
* Dependency injection module that overrides Langium default services and
* contributes the declared `Packet` services.
*/
export const PacketModule: Module<PacketServices, PartialLangiumServices & PacketAddedServices> = {
export const PacketModule: Module<
PacketServices,
PartialLangiumCoreServices & PacketAddedServices
> = {
parser: {
TokenBuilder: () => new PacketTokenBuilder(),
ValueConverter: () => new CommonValueConverter(),
@@ -50,16 +59,16 @@ export const PacketModule: Module<PacketServices, PartialLangiumServices & Packe
* @param context - Optional module context with the LSP connection
* @returns An object wrapping the shared services and the language-specific services
*/
export function createPacketServices(context: DefaultSharedModuleContext = EmptyFileSystem): {
shared: LangiumSharedServices;
export function createPacketServices(context: DefaultSharedCoreModuleContext = EmptyFileSystem): {
shared: LangiumSharedCoreServices;
Packet: PacketServices;
} {
const shared: LangiumSharedServices = inject(
createDefaultSharedModule(context),
const shared: LangiumSharedCoreServices = inject(
createDefaultSharedCoreModule(context),
MermaidGeneratedSharedModule
);
const Packet: PacketServices = inject(
createDefaultModule({ shared }),
createDefaultCoreModule({ shared }),
PacketGeneratedModule,
PacketModule
);

View File

@@ -1,11 +1,16 @@
import type {
DefaultSharedModuleContext,
LangiumServices,
LangiumSharedServices,
DefaultSharedCoreModuleContext,
LangiumCoreServices,
LangiumSharedCoreServices,
Module,
PartialLangiumServices,
PartialLangiumCoreServices,
} from 'langium';
import {
EmptyFileSystem,
createDefaultCoreModule,
createDefaultSharedCoreModule,
inject,
} from 'langium';
import { EmptyFileSystem, createDefaultModule, createDefaultSharedModule, inject } from 'langium';
import { MermaidGeneratedSharedModule, PieGeneratedModule } from '../generated/module.js';
import { PieTokenBuilder } from './tokenBuilder.js';
@@ -24,13 +29,13 @@ type PieAddedServices = {
/**
* Union of Langium default services and `Pie` services.
*/
export type PieServices = LangiumServices & PieAddedServices;
export type PieServices = LangiumCoreServices & PieAddedServices;
/**
* Dependency injection module that overrides Langium default services and
* contributes the declared `Pie` services.
*/
export const PieModule: Module<PieServices, PartialLangiumServices & PieAddedServices> = {
export const PieModule: Module<PieServices, PartialLangiumCoreServices & PieAddedServices> = {
parser: {
TokenBuilder: () => new PieTokenBuilder(),
ValueConverter: () => new PieValueConverter(),
@@ -51,15 +56,19 @@ export const PieModule: Module<PieServices, PartialLangiumServices & PieAddedSer
* @param context - Optional module context with the LSP connection
* @returns An object wrapping the shared services and the language-specific services
*/
export function createPieServices(context: DefaultSharedModuleContext = EmptyFileSystem): {
shared: LangiumSharedServices;
export function createPieServices(context: DefaultSharedCoreModuleContext = EmptyFileSystem): {
shared: LangiumSharedCoreServices;
Pie: PieServices;
} {
const shared: LangiumSharedServices = inject(
createDefaultSharedModule(context),
const shared: LangiumSharedCoreServices = inject(
createDefaultSharedCoreModule(context),
MermaidGeneratedSharedModule
);
const Pie: PieServices = inject(createDefaultModule({ shared }), PieGeneratedModule, PieModule);
const Pie: PieServices = inject(
createDefaultCoreModule({ shared }),
PieGeneratedModule,
PieModule
);
shared.ServiceRegistry.register(Pie);
return { shared, Pie };
}

View File

@@ -120,7 +120,7 @@ describe('pie', () => {
\t"GitHub" \t : \t 100
\t"GitLab" \t : \t 50
`,
])('should handle regular secions', (context: string) => {
])('should handle regular sections', (context: string) => {
const result = parse(context);
expectNoErrorsOrAlternatives(result);
expect(result.value.$type).toBe(Pie);

4817
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

82
scripts/size.ts Normal file
View File

@@ -0,0 +1,82 @@
/* eslint-disable no-console */
import type { Metafile } from 'esbuild';
import { readFile } from 'fs/promises';
import { globby } from 'globby';
import { markdownTable } from 'markdown-table';
export const getSizes = (metafile: Metafile) => {
const { outputs } = metafile;
const sizes = Object.keys(outputs)
.filter((key) => key.endsWith('js') && !key.includes('chunk'))
.map((key) => {
const { bytes } = outputs[key];
return [key.replace('dist/', ''), bytes];
});
return sizes;
};
const readStats = async (path: string): Promise<Record<string, number>> => {
const files = await globby(path);
const contents = await Promise.all(files.map((file) => readFile(file, 'utf-8')));
const sizes = contents.flatMap((content) => getSizes(JSON.parse(content)));
return Object.fromEntries(sizes);
};
const formatBytes = (bytes: number): string => {
if (bytes == 0) {
return '0 Bytes';
}
const base = 1024;
const decimals = 2;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const i = Math.floor(Math.log(bytes) / Math.log(base));
return parseFloat((bytes / Math.pow(base, i)).toFixed(decimals)) + ' ' + sizes[i];
};
const formatSize = (bytes: number): string => {
const formatted = formatBytes(bytes);
if (formatted.includes('Bytes')) {
return formatted;
}
return `${formatBytes(bytes)} (${bytes} Bytes)`;
};
const percentageDifference = (oldValue: number, newValue: number): string => {
const difference = Math.abs(newValue - oldValue);
const avg = (newValue + oldValue) / 2;
const percentage = (difference / avg) * 100;
const roundedPercentage = percentage.toFixed(2); // Round to two decimal places
if (roundedPercentage === '0.00') {
return '0.00%';
}
const sign = newValue > oldValue ? '+' : '-';
return `${sign}${roundedPercentage}%`;
};
const main = async () => {
const oldStats = await readStats('./cypress/snapshots/stats/base/**/*.json');
const newStats = await readStats('./cypress/snapshots/stats/head/**/*.json');
const diff = Object.entries(newStats)
.filter(([, value]) => value > 2048)
.map(([key, value]) => {
const oldValue = oldStats[key];
const delta = value - oldValue;
const output = [
key,
formatSize(oldValue),
formatSize(value),
formatSize(delta),
percentageDifference(oldValue, value),
];
return output;
})
.filter(([, , , delta]) => delta !== '0 Bytes');
if (diff.length === 0) {
console.log('No changes in bundle sizes');
return;
}
console.log(
markdownTable([['File', 'Previous Size', 'New Size', 'Difference', '% Change'], ...diff])
);
};
void main().catch((e) => console.error(e));