npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tresinternet/trex

v7.2.0

Published

TRES' asset building tool

Downloads

244

Readme

TREX

TREX is TRES internet's internal build- and development tool.

Build

TREX can be used to build the Design System, used for development and presentation purposes. This tool executes the following build-steps (in order):

  1. clean
  2. html, index, pin, library (parallel)
  3. mail
  4. scripts
  5. styles
  6. icons
  7. assets

The purpose of each step is described below.

Assets

Copy all assets to the corresponding folder. This task includes:

  • Copying assets via copyAssets
  • Optimizing images via optimizeImages
  • Generating *.webp files via webPImages
  • Re-running the html task (in TASK or SERVE mode)

Clean

Clear all previously generated files

HTML

Parse all Nunjunck-templates and save them as *.html

Icons

Copy all icons to the corresponding folder. This task includes:

  • Copying icons via copyIcons
  • Optimizing icons via optimizeIcons
  • Re-running the html task (in TASK or SERVE mode)

Library

Copy all Design System files to the corresponding folder

Index

Copy the index file to the corresponding folder

Mail

Parse all *.mjml-templates and save them as *.html

Optimize Images

Optimize all images in the output directory using gulp-imagemin

Optimize Icons

Optimize all SVG icons in the output directory using gulp-imagemin with SVGO

Pin

Generate a pincode.config-file that prevents unauthorized access to the deployed Design System

Scripts

Depending on the scripts.useModernJs-property, the following steps are executed:

Modern JavaScript

Compile all *.js- and *.ts-files and run them through Webpack for TypeScript and ES6 support.

Legacy JavaScript

Minify all *.js files and run them trough Babel for ES6 support. Uses the include()-plugin to import javascript files from within other javascript files.

Styles

Parse all *.scss-files, compile them, run them trough PostCSS, generate sourcemaps and save them as *.css

Deploy

This tool is also used to deploy the assets to a server, to be used with an Umbraco installation. It omits a few steps from the build-task, and executes the following steps (in order):

  1. clean
  2. scripts
  3. styles
  4. icons
  5. assets

Serve

TREX can also be used to serve the Design System locally. It watches for changes in the source files and automatically rebuilds the Design System. Changes in the Design System are automatically reloaded in the browser using BrowserSync.

The following watch patterns are set up:

  • config.paths.html.watch → triggers html task
  • config.paths.library.watch → triggers library task
  • config.paths.mail.watch → triggers mail task (if configured)
  • config.paths.scripts.watch → triggers scripts task
  • config.paths.styles.watch → triggers styles task
  • config.paths.icons.watch → triggers icons task (if configured)
  • config.paths.assets.watch → triggers assets task (if configured)

The directories that are watched for changes can be configured in the config-object, as described below.

Callbacks

The callback-property can be used to execute a function after the task is finished. The function receives an object with the following gulp functions, that can be used to trigger other tasks:

  • assets
  • html
  • icons
  • mail
  • scripts
  • styles

Layout modifications

The getLayoutModifications-function can be used to get the layout modifications for the Design System. It accepts a path to the directory containing the stylesheets. It parses all *.scss-files in the directory and searches for all layout modifications, that can be defined like this:

/**
* Layout modification: Modification name
* Layout modification category: modification category
* Layout modification value: .modification--class
* Layout modification description: Modification description
* Layout modification image: /dist/assets/umbraco/<directory>/<image>.png
*/

The output can be used to generate an overview of all layout modifications, and the JSON that can be used to generate the layout modifications in Umbraco.

RTE Styles

TREX can also copy the RTE styles to the folder used by Umbraco. The input and output paths are defined in the config-object, as described below.

Development

To develop TREX, update the TypeScript files (index.ts, gulp-multi-dest.ts, types.d.ts).

Before publishing, build the TypeScript files:

npm run build

Testing it in another project is recommended. This can be done by linking the local version of TREX in the package.json-file of the other project. In the root of the TREX-project, run the following command:

pnpm link -global

In the root of the other project (where the package.json-file is located), run the following command:

pnpm link --global @tresinternet/trex

(Note that any existing references to @tresinternet/trex should be removed before linking TREX). Alternatively, you can add the following to the package.json-file of the other project:

"dependencies": {
	"@tresinternet/trex": "file://<path-to-trex-project>/tres-internet-library-trex/",
}

Usage

Install TREX

pnpm i @tresinternet/trex

Run dev-server

This command builds the Design System and starts the dev-server.

npx gulp serve

Build Design System

This command builds the Design System. Mainly used in CI/CD pipelines for deployment of the Design System.

npx gulp build

Build for Production

This command builds the Design System for Umbraco. Mainly used in CI/CD pipelines for deployment along with the Umbraco deployment.

npx gulp deploy

Copy RTE Styles

TREX can also copy the RTE styles to the folder used by Umbraco. This task copies all files that match the glob rte_*.css from the config.paths.styles.output-directory to the dest_rte-directory.

npx gulp rte-copy

Migration

v5.x.x to v6.x.x

The following configuration keys are required in the config-object:

  • config.paths.rte.output - The path to the directory where the RTE styles are copied to.

Example values:

config: {
	...
	paths: {
		...
		rte: {
			output: path.posix.join(root, "wwwroot", "css")
		}
		...
	}
}

v3.x.x to v5.x.x

The following configuration keys are required in the config-object:

  • config.scripts - Script configuration

Example values:

config: {
	scripts: {
		useModernJs: true,
		minify: { "builtIns": false, "mangle": true }
	},
}

The following configuration keys are optional in the config-object:

  • config.paths.assets.webp - WebP input paths. Make sure the input paths only contain images.

Example values:

config: {
	paths: {
		assets: {
			webp: [
				path.posix.join(base.dest, "assets", "images", "**", "*.jpg"),
				path.posix.join(base.dest, "assets", "images", "**", "*.jpeg"),
				path.posix.join(base.dest, "assets", "images", "**", "*.png")
			]
		}
	}
}

Configuration

TREX can be configured by adding a gulpfile.js-file to the root of your project.

Gulpfile.js

The gulpfile.js-file should init the TREX-package. This function takes the gulp-task and a config-object as parameters.

const gulp = require('gulp');
const trex = require('@tresinternet/trex');

const config = {
  // Config
};

trex.init(gulp, config);

Config

The config-object has the following properties:

| Property | Description | | --------- | -------------------------------------------------------------------------------------------------------------------------------- | | src | The base path of the source directory | | dest | The base path of the destination directory | | paths | An object containing the paths of the source, destination and watch directories. Accepts additional properties for certain tasks | | njk | An object containing the options for the Nunjucks-parser | | postcss | An object containing the options for the PostCSS-parser | | scripts | An object containing the options for the Javascript-parser | | pin | The pincode used to prevent unauthorized access to the deployed Design System |

Paths

The paths-property contains the paths of the source, destination and watch directories. It accepts additional properties for certain tasks.

All paths are defined as glob-patterns and accept an array of globs. See https://docs.python.org/3/library/glob.html for more information. Also, the path.posix.join-function is used to join the paths. See https://nodejs.org/api/path.html#path_path_posix_join_paths for more information.

| Path property | Description | Used by tasks | | ------------- | ---------------------------------------------------------------------------------------------- | ----------------- | | input | The glob that is used as the entry point for the specific tasks | All | | output | The output directory of the assets generated for this task | All | | watch | The glob that is used to watch for changes | All | | path | The path of the source directory. Necessary for the Nunjucks-parser | html, mail | | index | The path of the index file. Used as entry-point for the Design System | library | | serve | The path of the directory that is served by the dev-server | library | | optimize | The glob pattern for files to optimize | assets, icons | | webp | The path of the images that should be converted to webP-images. Make sure you only pass images | assets | | callback | The callback-function that is executed after the task is finished | Most tasks |

An example of the paths-property:

paths: {
 clean: {
	input: [
		path.posix.join(base.dest, '**', '*'),
	]
 },
 styles: {
	input: path.posix.join(base.src, 'stylesheets', '*.scss'),
	output: [path.posix.join(base.dest, 'assets/stylesheets')],
	watch: [
		// In addition to the `*.scss`-files, the `tailwind.config.js`-file is also watched for changes.
		path.posix.join(base.src, 'stylesheets', '**', '*.scss'),
		'./tailwind.config.js'
	]
 },
 html: {
	input: [
		path.posix.join(base.src, 'html', '**', '*.njk'),
	],
	output: path.posix.join(base.dest, 'html'),
	path: path.posix.join(base.src, 'html'),
	watch: path.posix.join(base.src, 'html', '**', '*.njk')
 },
 mail: {
	input: [path.posix.join(base.src, 'html', '**', '*.mjml')],
	output: path.posix.join(base.dest, 'html'),
	watch: path.posix.join(base.src, 'html', '**', '*.mjml')
 },
 assets: {
	input: path.posix.join(base.src, 'assets', '**', '*'),
	output: path.posix.join(base.dest, 'assets'),
	watch: path.posix.join(base.src, 'assets', '**', '*')
 },
 library: {
	input: path.posix.join(base.src, 'library', '**', '*'),
	output: path.posix.join(base.dest, 'library'),
	serve: path.posix.join(base.dest),
	index: path.posix.join('library', 'index.html'),
	watch: path.posix.join(base.src, 'library', 'library.json')
 },
 scripts: {
	input: path.posix.join(base.src, 'scripts', '*.js'),
	output: path.posix.join(base.dest, 'assets/scripts'),
	watch: path.posix.join(base.src, 'scripts', '**', '*.js')
 },
 optimize: {
	input: [
		path.posix.join(base.src, 'assets', 'images', '**', '*'),
		path.posix.join(base.src, 'html', 'icons', '**', '*')
	],
	// The output-directory is omitted, because the optimize-task optimizes the images and icons in-place.
	watch: [
		path.posix.join(base.src, 'assets', 'images', '**', '*'),
		path.posix.join(base.src, 'html', 'icons', '**', '*')
	],
	callback: function() {
	// Inject the icons into the Nunjucks-parser
	config.njk.data.icons = dirTree('./src/html/icons', {
		attributes: ['type', 'extension']
	});
	}
 },
 icons: {
	input: path.posix.join(base.src, 'html', 'icons', '**', '*'),
	output: path.posix.join(base.dest, 'icons'),
	watch: path.posix.join(base.src, 'html', 'icons', '**', '*')
 },
 rte: {
	output: path.posix.join(root, "wwwroot", "css")
 }
},

In order to use base.dest and base.src in the paths-property, the base-object is defined as follows:

const base = {
  src: './src',
  dest: './dist'
};

Nunjucks

To configure the Nunjucks-parser, the njk-property is used. All properties are nested in a data-object. The following properties should be defined:

| Property | Description | | ---------- | --------------------------------------------------------------------------------------------------------------------------------- | | base | The base path of the Design System. Should be an empty string when served locally, or the URL of the base path when served online | | client | The name of the client. Used to display the title of the Design System | | tailwind | The path of the tailwind.config-configuration file. Used to extract some data for the Design System | | icons | The path of the icons-directory, wrapped in a dirTree-function. Used to display the icons |

An example of the njk-property:

njk: {
 data: {
  base: process.argv.find(arg => arg === 'serve' || arg === 'build' || arg === 'html') ? '' : 'https://example.com',
  client: 'TRES internet',
  tailwind: require('./tailwind.config'),
  icons: dirTree('./src/html/icons', {
   attributes: ['type', 'extension']
  })
 }
}

Postcss

To configure the Postcss-parser, the postcss-property is used. The following properties should be defined:

| Property | Description | | --------- | --------------------------- | | plugins | An array of Postcss-plugins |

For more information about the plugins, see the PostCss documentation at https://postcss.org/.

An example of the postcss-property:

postcss: {
 // Only use PurgeCSS when building or deploying the Design System, or when running the styles-task directly
 plugins: process.argv.find(arg => arg === 'styles' || arg === 'build' || arg === 'deploy') ? [
  require('tailwindcss'),
  postcssPresetEnv({
   // ...
  }),
  require('@fullhuman/postcss-purgecss')({
   content: [
    path.posix.join(base.src, '/**/*.njk'),
    path.posix.join(base.dest, '/**/*.html')
   ],
   defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || [],
  })
 ] : [
  require('tailwindcss'),
  postcssPresetEnv({
   // ...
  }),
 ]
},

Scripts

To configure the Javascript-parser, the scripts-property is used. The following properties can be defined:

| Property | Description | | -------- | ---------------------------------------------------------------------------------------------------------------------------- | | minify | The babel-minify options - https://babeljs.io/docs/gulp-babel-minify#minifyoptions. Set to false to disable minification |

BrowserSync

To configure the BrowserSync-server, the browserSync-property is used. See the BrowserSync documentation for more information.

An example of the browserSync-property:

browserSync: {
 ghostMode: false,
},

Pin

To protect the Design System from being accessed by unauthorized users, the pin-property is used. This is a simple 5-digit pin.

Full example

import { arg, init, getEditors, getLayoutModifications } from '@tresinternet/trex'
import type { Config } from '@tresinternet/trex'
import dirTree from 'directory-tree'
import gulp from 'gulp'
import postcssPresetEnv from 'postcss-preset-env'
import path from 'path'

const root = ''

const base = {
	src: './src',
	dest: root + '/dist',
}

const config: Config = {
	src: base.src,
	dest: base.dest,
	pin: 12345,
	paths: {
		clean: {
			input: path.posix.join(base.dest),
		},
		styles: {
			input: path.posix.join(base.src, 'stylesheets', '*.scss'),
			output: path.posix.join(base.dest, 'assets/stylesheets'),
			watch: [
				path.posix.join(base.src, 'stylesheets', '**', '*.scss'),
			],
			callback: function (tasks: any) {
				const layoutModifications = getLayoutModifications(path.posix.join(base.src, 'stylesheets'))

				if (config.njk.data.layoutModifications !== layoutModifications) {
					config.njk.data.layoutModifications = layoutModifications
					tasks.html()
				}
			},
		},
		html: {
			input: [
				path.posix.join(base.src, 'html', '**', '*.njk'),
				'!' + path.posix.join(base.src, 'html', '**', '_macros', '*.njk'),
				'!' + path.posix.join(base.src, 'html', '**', '_*.njk'),
			],
			output: path.posix.join(base.dest, 'html'),
			path: path.posix.join(base.src, 'html'),
			watch: path.posix.join(base.src, 'html', '**', '*.njk'),
		},
		mail: {
			input: [path.posix.join(base.src, 'html', '**', '*.mjml')],
			output: path.posix.join(base.dest, 'html'),
			path: path.posix.join(base.src, 'html'),
			watch: path.posix.join(base.src, 'html', '**', '*.mjml'),
		},
		assets: {
			input: path.posix.join(base.src, 'assets', '**', '*'),
			watch: [
				path.posix.join(base.src, 'assets', '**', '*'),
			],
			output: path.posix.join(base.dest, 'assets'),
			optimize: path.posix.join(base.dest, 'assets', 'images', '**', '*'),
			webp: [
				path.posix.join(base.dest, 'assets', 'images', '**', '*.jpg'),
				path.posix.join(base.dest, 'assets', 'images', '**', '*.jpeg'),
				path.posix.join(base.dest, 'assets', 'images', '**', '*.png'),
			],
			callback: function () {
				config.njk.data.icons = dirTree('./src/html/icons', {
					attributes: ['type', 'extension'],
				})
			},
		},
		index: {
			input: path.posix.join(base.src, 'index.html'),
			output: path.posix.join(base.dest),
		},
		library: {
			input: [
				path.posix.join('./node_modules', '@tresinternet', 'design-system', 'dist', '**', '*'),
				path.posix.join('library.json'),
			],
			output: path.posix.join(base.dest, 'library'),
			serve: path.posix.join(base.dest),
			index: path.posix.join('library', 'index.html'),
			watch: path.posix.join('library.json'),
		},
		scripts: {
			input: path.posix.join(base.src, 'scripts', '*.js'),
			output: path.posix.join(base.dest, 'assets/scripts'),
			watch: path.posix.join(base.src, 'scripts', '**', '*.js'),
		},
		optimize: {
		},
		icons: {
			input: path.posix.join(base.src, 'html', 'icons', '**', '*'),
			output: path.posix.join(base.dest, 'icons'),
			optimize: path.posix.join(base.dest, 'icons', '**', '*'),
			watch: path.posix.join(base.src, 'html', 'icons', '**', '*'),
		},
		rte: {
			output: path.posix.join(root, 'wwwroot', 'css'),
		},
	},
	njk: {
		data: {
			base: process.argv.find(arg => arg === 'serve' || arg === 'deploy' || arg === 'html') ? '' : arg.path as string || '',
			client: 'TREX',
			icons: dirTree('./src/html/icons', {
				attributes: ['type', 'extension'],
			}),
			editors: getEditors(path.posix.join(root, 'TREX', 'Configuration')),
			layoutModifications: getLayoutModifications(path.posix.join(base.src, 'stylesheets')),
			cachebuster: Math.floor(Math.random() * (9999999 - 1111111) + 1111111),
		},
	},
	postcss: {
		plugins: process.argv.find(arg => arg === 'styles' || arg === 'build') ? [

			postcssPresetEnv({
				browsers: 'last 2 versions',
				stage: 3,
				features: {
					'nesting-rules': true,
				},
			}),
		] : [

		],
	},
	scripts: {
		minify: { 'builtIns': false, 'mangle': true },
		useModernJs: true,
	},
}

init(gulp, config)