Skip to content

@presencelearning/frontend-devtools

Developer tools and scripts for Presence Learning Angular applications.

Terminal window
npm install --save-dev @presencelearning/frontend-devtools

Generate Angular services with inlined and optimized SVG content for better bundle sizes and type safety.

Terminal window
# Use default paths (./src/assets/svg/*.svg -> ./src/build/svg-inline-ng-plugin.service.ts)
pl-generate-svg
# Custom paths
pl-generate-svg "./src/assets/icons/*.svg" "./src/services/icons.service.ts"
import { generateSvgService } from '@presencelearning/frontend-devtools/svg';
await generateSvgService({
svgGlob: './src/assets/svg/*.svg',
outputFile: './src/build/svg-inline-ng-plugin.service.ts',
includeAngularDecorator: true, // default: true
svgoConfig: {
/* custom SVGO config */
},
});
  • Scans directory for SVG files using glob patterns
  • Optimizes SVGs with SVGO
  • Generates typed Angular service with @Injectable
  • Inlines SVG content for zero runtime loading
  • Supports custom SVGO configuration
  • Full TypeScript support
{
"scripts": {
"svg": "pl-generate-svg"
}
}

Create a svgo.config.js file in your project root:

module.exports = {
multipass: true,
plugins: [
{
name: 'preset-default',
params: {
overrides: {
inlineStyles: {
onlyMatchedOnce: false,
},
removeViewBox: false,
},
},
},
'prefixIds',
],
};
// The generated service
@Injectable({ providedIn: 'root' })
export class SvgInlineNgPluginService {
svgs: Record<string, { html: string }> = {
'icon-name': { html: `<svg>...</svg>` },
};
}
// In your component
import { SvgInlineNgPluginService } from './build/svg-inline-ng-plugin.service';
@Component({
selector: 'app-icon',
template: '<div [innerHTML]="getSvg(\'icon-name\')"></div>',
})
export class IconComponent {
constructor(private svgService: SvgInlineNgPluginService) {}
getSvg(name: string) {
return this.svgService.svgs[name]?.html || '';
}
}

Extracts .map files from your build output to a separate directory. Useful for uploading to error monitoring services (Sentry, Rollbar) while keeping them out of production bundles.

Terminal window
# Extract from default ./dist to ./sourcemaps
npx pl-extract-sourcemaps
# Custom dist path (searches recursively)
npx pl-extract-sourcemaps ./dist/my-app
# Custom dist and output paths
npx pl-extract-sourcemaps ./dist ./maps
{
"scripts": {
"build:production": "ng build --configuration production",
"postbuild:production": "pl-extract-sourcemaps"
}
}
import { extractSourcemaps } from '@presencelearning/frontend-devtools/sourcemaps';
await extractSourcemaps({
distPath: './dist',
outputPath: './sourcemaps',
});

The tool includes comprehensive path validation to prevent dangerous operations:

  • Prevents output path from being the same as dist path
  • Prevents nested path conflicts (output inside dist or vice versa)
  • Prevents deletion of system root directories
  • Prevents deletion of current directory

If you have node-scripts/extract-sourcemaps.mjs in your project:

Before:

{
"scripts": {
"extract-sourcemaps": "node ./node-scripts/extract-sourcemaps.mjs"
}
}

After:

{
"scripts": {
"extract-sourcemaps": "pl-extract-sourcemaps"
}
}

For projects with nested dist directories (like ./dist/therapy-essentials):

{
"scripts": {
"extract-sourcemaps": "pl-extract-sourcemaps ./dist/therapy-essentials"
}
}

Then remove your local node-scripts/extract-sourcemaps.mjs file.


The following tools are planned for future releases:

  • Cloudflare Utilities — API helpers for Pages deployments and DNS management
  • SSL Certificate Generator — Self-signed certificates for local HTTPS development

Have a common dev tool pattern that could be shared across projects? Contributions welcome.


Source: packages/devtools