1- /* eslint-disable @typescript-eslint/no-non-null-assertion */
2- import ts from 'typescript' ;
1+ import fs from 'fs' ;
2+ import { copyFile , mkdir , readdir , readFile , rm , writeFile } from 'fs/promises' ;
3+ import path from 'path' ;
4+ import { fileURLToPath } from 'url' ;
35import commonjs from '@rollup/plugin-commonjs' ;
46import rollupTerser from '@rollup/plugin-terser' ;
57import rollupTypescript from '@rollup/plugin-typescript' ;
68import CleanCSS from 'clean-css' ;
7- import fs from 'fs' ;
8- import { mkdir , readFile , readdir , rm , writeFile , copyFile } from 'fs/promises' ;
99import MagicString from 'magic-string' ;
10- import path from 'path' ;
1110import { rollup } from 'rollup' ;
12- import { fileURLToPath } from 'url ' ;
11+ import ts from 'typescript ' ;
1312import { webfont } from 'webfont' ;
1413import { toArray } from '../src/shared/util' ;
1514import { components } from './components' ;
@@ -20,11 +19,17 @@ import type { OutputOptions, Plugin, RollupBuild, RollupOptions, SourceMapInput
2019const __dirname = path . dirname ( fileURLToPath ( import . meta. url ) ) ;
2120
2221const SRC_DIR = path . join ( __dirname , '../src/' ) ;
22+ const DIST_DIR = path . join ( __dirname , '../dist' ) ;
23+
2324const languageIds = fs
2425 . readdirSync ( path . join ( SRC_DIR , 'languages' ) )
2526 . map ( f => f . slice ( 0 , - '.js' . length ) )
2627 . sort ( ) ;
2728const pluginIds = fs . readdirSync ( path . join ( SRC_DIR , 'plugins' ) ) . sort ( ) ;
29+ const themeIds = fs
30+ . readdirSync ( path . join ( SRC_DIR , '../themes' ) )
31+ . map ( f => f . slice ( 0 , - '.css' . length ) )
32+ . sort ( ) ;
2833
2934async function loadComponent ( id : string ) {
3035 let file ;
@@ -54,8 +59,6 @@ async function minifyCSS () {
5459 }
5560 }
5661
57- const DIST = path . join ( __dirname , '../dist' ) ;
58-
5962 const clean = new CleanCSS ( { } ) ;
6063
6164 await Promise . all (
@@ -69,7 +72,7 @@ async function minifyCSS () {
6972 console . warn ( `${ file } : ${ warn } ` ) ;
7073 }
7174
72- const targetFile = path . join ( DIST , target ) ;
75+ const targetFile = path . join ( DIST_DIR , target ) ;
7376 await mkdir ( path . dirname ( targetFile ) , { recursive : true } ) ;
7477 await writeFile ( targetFile , output . styles , 'utf-8' ) ;
7578 } )
@@ -277,7 +280,7 @@ const inlineRegexSourcePlugin: Plugin = {
277280 */
278281const lazyGrammarPlugin : Plugin = {
279282 name : 'lazy-grammar' ,
280- renderChunk ( code ) {
283+ renderChunk ( code ) {
281284 const str = new MagicString ( code ) ;
282285 str . replace (
283286 / ^ (?< indent > [ \t ] + ) g r a m m a r : ( \{ [ \s \S ] * ?^ \k<indent > \} ) / m,
@@ -287,7 +290,7 @@ const lazyGrammarPlugin: Plugin = {
287290 } ,
288291} ;
289292
290- function toRenderedChunk ( s : MagicString ) : { code : string ; map : SourceMapInput } {
293+ function toRenderedChunk ( s : MagicString ) : { code : string ; map : SourceMapInput } {
291294 return {
292295 code : s . toString ( ) ,
293296 map : s . generateMap ( { hires : true } ) as SourceMapInput ,
@@ -310,7 +313,7 @@ const terserPlugin = rollupTerser({
310313 keep_classnames : true ,
311314} ) ;
312315
313- async function clean ( ) {
316+ async function clean ( ) {
314317 const outputDir = path . join ( __dirname , '../dist' ) ;
315318 const typesDir = path . join ( __dirname , '../types' ) ;
316319 await Promise . all ( [
@@ -325,7 +328,7 @@ async function copyComponentsJson () {
325328 await copyFile ( from , to ) ;
326329}
327330
328- async function buildTypes ( ) {
331+ async function buildTypes ( ) {
329332 await mkdir ( './types' ) ;
330333
331334 // Copy existing type definitions
@@ -359,7 +362,7 @@ async function buildTypes() {
359362 program . emit ( ) ;
360363}
361364
362- async function buildJS ( ) {
365+ async function buildJS ( ) {
363366 const input : Record < string , string > = {
364367 'index' : path . join ( SRC_DIR , 'index.ts' ) ,
365368 'shared' : path . join ( SRC_DIR , 'shared.ts' ) ,
@@ -373,15 +376,20 @@ async function buildJS() {
373376
374377 const defaultRollupOptions : RollupOptions = {
375378 input,
376- plugins : [ rollupTypescript ( { module : 'esnext' } ) ] ,
379+ plugins : [
380+ rollupTypescript ( { module : 'esnext' } ) ,
381+ lazyGrammarPlugin ,
382+ dataInsertPlugin ,
383+ inlineRegexSourcePlugin ,
384+ terserPlugin ,
385+ ] ,
377386 } ;
378387
379388 const defaultOutputOptions : OutputOptions = {
380389 dir : './dist' ,
381390 chunkFileNames : '_chunks/[name]-[hash].js' ,
382391 validate : true ,
383392 sourcemap : 'hidden' ,
384- plugins : [ lazyGrammarPlugin , dataInsertPlugin , inlineRegexSourcePlugin , terserPlugin ] ,
385393 } ;
386394
387395 const bundles : Record <
@@ -411,10 +419,10 @@ async function buildJS() {
411419 ...defaultRollupOptions ,
412420 input : {
413421 'prism' : path . join ( SRC_DIR , 'auto-start.ts' ) ,
414- }
422+ } ,
415423 } ,
416424 outputOptions : defaultOutputOptions ,
417- }
425+ } ,
418426 } ;
419427
420428 try {
@@ -430,4 +438,74 @@ async function buildJS() {
430438 }
431439}
432440
433- runTask ( series ( clean , parallel ( buildTypes , buildJS , series ( treeviewIconFont , minifyCSS ) ) , copyComponentsJson ) ) ;
441+ // Helper to get file size in bytes, or 0 if not found
442+ const getFileSize = async ( filePath : string ) => {
443+ try {
444+ const stat = await fs . promises . stat ( filePath ) ;
445+ return stat . size ;
446+ }
447+ catch {
448+ return 0 ;
449+ }
450+ } ;
451+
452+ async function calculateFileSizes ( ) {
453+ type FileSizes = {
454+ css ?: number ;
455+ js ?: number ;
456+ } ;
457+
458+ const ret : Record < string , FileSizes & Record < string , FileSizes > > = {
459+ core : { } ,
460+ themes : { } ,
461+ languages : { } ,
462+ plugins : { } ,
463+ } ;
464+
465+ ret . core . js = await getFileSize ( path . join ( DIST_DIR , 'index.js' ) ) ;
466+
467+ for ( const category of [ 'themes' , 'languages' , 'plugins' ] ) {
468+ let ids = themeIds ;
469+ if ( category === 'languages' ) {
470+ ids = languageIds ;
471+ }
472+ else if ( category === 'plugins' ) {
473+ ids = pluginIds ;
474+ }
475+
476+ for ( const id of ids ) {
477+ ret [ category ] [ id ] = { } ;
478+
479+ for ( const ext of [ 'js' , 'css' ] ) {
480+ if (
481+ ( ext === 'css' &&
482+ ( category === 'languages' || components [ category ] [ id ] . noCSS ) ) ||
483+ ( category === 'themes' && ext === 'js' )
484+ ) {
485+ continue ;
486+ }
487+
488+ const filePath = path . join (
489+ DIST_DIR ,
490+ category ,
491+ category === 'plugins' ? `prism-${ id } ` : id
492+ ) ;
493+ ret [ category ] [ id ] [ ext as 'css' | 'js' ] = await getFileSize ( `${ filePath } .${ ext } ` ) ;
494+ }
495+ }
496+ }
497+
498+ await fs . promises . writeFile (
499+ path . join ( DIST_DIR , 'file-sizes.json' ) ,
500+ JSON . stringify ( ret , null , '\t' )
501+ ) ;
502+ }
503+
504+ runTask (
505+ series (
506+ clean ,
507+ parallel ( buildTypes , buildJS , series ( treeviewIconFont , minifyCSS ) ) ,
508+ copyComponentsJson ,
509+ calculateFileSizes
510+ )
511+ ) ;
0 commit comments