@divriots/jampack 0.32.0 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
File without changes
package/README.md CHANGED
File without changes
package/dist/cache.js CHANGED
@@ -1,13 +1,15 @@
1
1
  import { hashSync as hasha } from 'hasha';
2
2
  import path from 'path';
3
- import * as fs from 'fs/promises';
3
+ import * as fsp from 'fs/promises';
4
4
  import { CACHE_VERSIONS } from './packagejson.js';
5
5
  const listOfCategories = ['img', 'img-ext'];
6
6
  function getCacheFolder(state) {
7
7
  return state.args.cache_folder || '.jampack/cache';
8
8
  }
9
9
  async function cleanCache(state, full) {
10
+ var _a;
10
11
  const CACHE_FOLDER = getCacheFolder(state);
12
+ const fs = (_a = state.vfs) !== null && _a !== void 0 ? _a : fsp;
11
13
  if (full) {
12
14
  try {
13
15
  await fs.rm(CACHE_FOLDER, { recursive: true });
@@ -66,9 +68,11 @@ function getLocation(state, hash, category) {
66
68
  return path.join(CACHE_FOLDER, category, getVersionOfCategory(category), hash);
67
69
  }
68
70
  async function getFromCache(state, category, hash) {
71
+ var _a;
69
72
  if (state.args.nocache) {
70
73
  return undefined;
71
74
  }
75
+ const fs = (_a = state.vfs) !== null && _a !== void 0 ? _a : fsp;
72
76
  const location = getLocation(state, hash, category);
73
77
  try {
74
78
  const buffer = await fs.readFile(path.join(location, 'data'));
@@ -81,9 +85,11 @@ async function getFromCache(state, category, hash) {
81
85
  return undefined;
82
86
  }
83
87
  async function addToCache(state, category, hash, data) {
88
+ var _a;
84
89
  if (state.args.nocache) {
85
90
  return;
86
91
  }
92
+ const fs = (_a = state.vfs) !== null && _a !== void 0 ? _a : fsp;
87
93
  const location = getLocation(state, hash, category);
88
94
  await fs.mkdir(location, { recursive: true });
89
95
  await fs.writeFile(path.join(location, 'data'), data.buffer);
package/dist/compress.js CHANGED
@@ -1,4 +1,4 @@
1
- import * as fs from 'fs/promises';
1
+ import * as fsp from 'fs/promises';
2
2
  import * as path from 'path';
3
3
  import { formatBytes } from './utils.js';
4
4
  import { globby } from 'globby';
@@ -8,7 +8,9 @@ import { compressJS } from './compressors/js.js';
8
8
  import { compressHTML } from './compressors/html.js';
9
9
  import { compressImage } from './compressors/images.js';
10
10
  const processFile = async (state, file, stats) => {
11
+ var _a;
11
12
  let writeData = undefined;
13
+ const fs = (_a = state.vfs) !== null && _a !== void 0 ? _a : fsp;
12
14
  try {
13
15
  const ext = path.extname(file);
14
16
  switch (ext) {
@@ -69,6 +71,8 @@ const processFile = async (state, file, stats) => {
69
71
  state.reportSummary(result);
70
72
  };
71
73
  export async function compressFolder(state, exclude) {
74
+ var _a;
75
+ const fs = (_a = state.vfs) !== null && _a !== void 0 ? _a : fsp;
72
76
  const spinner = ora(getProgressText(state)).start();
73
77
  const globs = ['**/**', '!_jampack/**']; // Exclude jampack folder because already compressed
74
78
  if (exclude)
package/dist/index.js CHANGED
File without changes
package/dist/optimize.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { globby } from 'globby';
2
2
  import * as path from 'path';
3
- import * as fs from 'fs/promises';
3
+ import * as fsp from 'fs/promises';
4
4
  import { getCanonicalCdnForUrl, getTransformer } from 'unpic';
5
5
  import * as cheerio from '@divriots/cheerio';
6
6
  import { isNumeric } from './utils.js';
@@ -26,9 +26,11 @@ function getIntAttr(img, attr) {
26
26
  return parsed;
27
27
  }
28
28
  async function analyse(state, file) {
29
+ var _a;
29
30
  console.log('▶ ' + file);
30
31
  // For processes to add into
31
32
  const appendToBody = {};
33
+ const fs = (_a = state.vfs) !== null && _a !== void 0 ? _a : fsp;
32
34
  const html = (await fs.readFile(path.join(state.dir, file))).toString();
33
35
  if (!html.includes('<html'))
34
36
  return;
@@ -37,6 +39,7 @@ async function analyse(state, file) {
37
39
  await processTag(state, file, $, 'img', 'src', processImage, theFold, appendToBody);
38
40
  await processTag(state, file, $, 'iframe', 'src', processIframe, theFold, appendToBody);
39
41
  await processTag(state, file, $, 'video', 'src', processVideo, theFold, appendToBody);
42
+ await processTag(state, file, $, 'meta[property$=":image"], meta[name$=":image"]', 'content', processMetaImage, theFold, appendToBody);
40
43
  // Remove the fold
41
44
  //
42
45
  if (theFold) {
@@ -148,7 +151,7 @@ function getTheFold($) {
148
151
  return 0;
149
152
  }
150
153
  async function processImage(state, htmlfile, img, isAboveTheFold) {
151
- var _a, _b;
154
+ var _a, _b, _c;
152
155
  /*
153
156
  * Attribute 'src'
154
157
  */
@@ -226,28 +229,21 @@ async function processImage(state, htmlfile, img, isAboveTheFold) {
226
229
  /*
227
230
  * Check for external images
228
231
  */
229
- if (!isLocal(attrib_src) &&
230
- isIncluded(attrib_src, config.image.external.src_include, config.image.external.src_exclude)) {
231
- // Don't process external images
232
- if (config.image.external.process === 'off')
232
+ const { external } = state.options.image;
233
+ if (isExternalImage(attrib_src, external)) {
234
+ if (external.process === 'off')
235
+ // Don't process external images
233
236
  return;
234
237
  try {
235
- if (config.image.external.process === 'download') {
236
- // Download external image for local processing
237
- attrib_src = await downloadExternalImage(state, htmlfile, attrib_src);
238
- }
239
- else if (typeof config.image.external.process === 'function') {
240
- // Custom processing for external image
241
- attrib_src = await config.image.external.process(attrib_src);
242
- }
243
- img.attr('src', attrib_src);
238
+ const external_src = await externalImage(attrib_src, state, htmlfile);
239
+ if (external_src)
240
+ img.attr('src', (attrib_src = external_src));
244
241
  }
245
242
  catch (e) {
246
- state.reportIssue(htmlfile, {
243
+ return state.reportIssue(htmlfile, {
247
244
  type: 'warn',
248
245
  msg: `Failed to process external image: ${attrib_src} - ${e.message}`,
249
- });
250
- return; // No more processing
246
+ }); // No more processing
251
247
  }
252
248
  }
253
249
  switch (config.image.cdn.process) {
@@ -299,7 +295,7 @@ async function processImage(state, htmlfile, img, isAboveTheFold) {
299
295
  /*
300
296
  * Loading image
301
297
  */
302
- const originalImage = await Resource.loadResource(state.dir, htmlfile, attrib_src);
298
+ const originalImage = await Resource.loadResource(state, htmlfile, attrib_src);
303
299
  // No file -> give up
304
300
  if (!originalImage) {
305
301
  state.reportIssue(htmlfile, {
@@ -336,7 +332,7 @@ async function processImage(state, htmlfile, img, isAboveTheFold) {
336
332
  const newSrc = path.join(path.dirname(attrib_src), path.basename(attrib_src, path.extname(attrib_src)) +
337
333
  `.${newImage.format}`);
338
334
  if (!state.compressedFiles.has(newFilename) && !state.args.nowrite) {
339
- fs.writeFile(newFilename, newImage.data);
335
+ await ((_b = state.vfs) !== null && _b !== void 0 ? _b : fsp).writeFile(newFilename, newImage.data);
340
336
  }
341
337
  // Mark new file as compressed
342
338
  state.compressedFiles.add(newFilename);
@@ -477,7 +473,7 @@ async function processImage(state, htmlfile, img, isAboveTheFold) {
477
473
  // https://twitter.com/jonsneyers/status/1346389917816008704?s=19
478
474
  const isLossless = mime === 'image/png' ||
479
475
  (mime === 'image/webp' &&
480
- ((_b = (await originalImage.getImageMeta())) === null || _b === void 0 ? void 0 : _b.isLossless));
476
+ ((_c = (await originalImage.getImageMeta())) === null || _c === void 0 ? void 0 : _c.isLossless));
481
477
  if (!isLossless) {
482
478
  sourcesToGenerate.push({
483
479
  mime: 'image/avif',
@@ -508,6 +504,103 @@ async function processImage(state, htmlfile, img, isAboveTheFold) {
508
504
  }
509
505
  }
510
506
  }
507
+ async function processMetaImage(state, htmlfile, meta) {
508
+ var _a, _b, _c;
509
+ const attribute = 'content';
510
+ let content = meta.attr(attribute);
511
+ if (!content)
512
+ return state.reportIssue(htmlfile, {
513
+ type: 'warn',
514
+ msg: `Missing [content] on meta - processing skipped.`,
515
+ });
516
+ // Setup to ignore
517
+ const { src_exclude, src_include, cdn, external } = state.options.image;
518
+ if (!isIncluded(content, src_include, src_exclude))
519
+ return;
520
+ /*
521
+ * Check for external images
522
+ */
523
+ if (isExternalImage(content, external)) {
524
+ if (external.process === 'off')
525
+ // Don't process external images
526
+ return;
527
+ try {
528
+ const external_content = await externalImage(content, state, htmlfile);
529
+ if (external_content)
530
+ meta.attr(attribute, (content = external_content));
531
+ }
532
+ catch (e) {
533
+ return state.reportIssue(htmlfile, {
534
+ type: 'warn',
535
+ msg: `Failed to process external image: ${attribute} - ${e.message}`,
536
+ }); // No more processing
537
+ }
538
+ }
539
+ const propName = meta.attr('property') ? 'property' : 'name';
540
+ const width = meta.closest(`meta[${propName}:width]`).attr(attribute);
541
+ switch (cdn.process) {
542
+ case 'off':
543
+ break;
544
+ case 'optimize':
545
+ let cdnTransformer = cdn.transformer;
546
+ if (cdnTransformer && !cdn.src_include) {
547
+ throw new Error('config.image.cdn.src_include is required when specifying a config.image.cdn.transformer');
548
+ }
549
+ if (!cdnTransformer) {
550
+ const canonical = getCanonicalCdnForUrl(content);
551
+ if (!canonical)
552
+ break;
553
+ cdnTransformer = getTransformer(canonical.cdn);
554
+ }
555
+ if (!cdnTransformer)
556
+ break;
557
+ if (!isIncluded(content, cdn.src_include || /.*/, cdn.src_exclude))
558
+ break;
559
+ if (!width)
560
+ return state.reportIssue(htmlfile, {
561
+ type: 'warn',
562
+ msg: `Missing or malformed'width' attribute for image ${content}, unable to perform CDN transform`,
563
+ });
564
+ meta.attr(attribute, (_b = (_a = cdnTransformer({ url: content, width: +width })) === null || _a === void 0 ? void 0 : _a.toString()) === null || _b === void 0 ? void 0 : _b.replace(UNPIC_DEFAULT_HOST_REGEX, '/'));
565
+ return;
566
+ }
567
+ /*
568
+ * Loading image
569
+ */
570
+ const originalImage = await Resource.loadResource(state, htmlfile, content);
571
+ if (!originalImage)
572
+ return state.reportIssue(htmlfile, {
573
+ type: 'erro',
574
+ msg: `Can't find img on disk ${attribute}="${content}"`,
575
+ });
576
+ /*
577
+ * Compress image
578
+ */
579
+ const newImage = await compressImage(state, await originalImage.getData(), {
580
+ resize: width ? { width: +width } : undefined,
581
+ toFormat: meta.closest(`meta[${propName}:type]`).attr(attribute) === 'image/png'
582
+ ? 'png'
583
+ : 'jpeg',
584
+ });
585
+ if ((newImage === null || newImage === void 0 ? void 0 : newImage.data) && newImage.data.length < (await originalImage.getLen())) {
586
+ meta.attr(attribute, path.join(path.dirname(content), path.basename(content, path.extname(content)) + `.${newImage.format}`));
587
+ const newFilename = path.join(path.dirname(originalImage.filePathAbsolute), path.basename(originalImage.filePathAbsolute, path.extname(originalImage.filePathAbsolute)) + `.${newImage.format}`);
588
+ if (!state.compressedFiles.has(newFilename)) {
589
+ if (!state.args.nowrite)
590
+ await ((_c = state.vfs) !== null && _c !== void 0 ? _c : fsp).writeFile(newFilename, newImage.data);
591
+ // Mark new file as compressed
592
+ state.compressedFiles.add(newFilename);
593
+ // Report compression result
594
+ state.reportSummary({
595
+ action: newFilename !== originalImage.filePathAbsolute
596
+ ? `${await originalImage.getExt()}->${newImage.format}`
597
+ : path.extname(originalImage.filePathAbsolute),
598
+ originalSize: await originalImage.getLen(),
599
+ compressedSize: newImage.data.length,
600
+ });
601
+ }
602
+ }
603
+ }
511
604
  const isIncluded = (src, includeConf, excludeConf) => !!src.match(includeConf) && (!excludeConf || !src.match(excludeConf));
512
605
  async function _generateSrcSet({ options }, startSrc, imageWidth, imageHeight, transformSrc) {
513
606
  // Start from original image
@@ -549,6 +642,7 @@ async function generateSrcSet(state, htmlfile, originalImage, startSrc, startSrc
549
642
  const imageHeight = (meta === null || meta === void 0 ? void 0 : meta.height) || 0;
550
643
  let previousImageSize = startSrcLength || Number.MAX_VALUE;
551
644
  return _generateSrcSet(state, startSrc, imageWidth, imageHeight, async (valueW) => {
645
+ var _a;
552
646
  const src = imageSrc(`@${valueW}w`);
553
647
  const absoluteFilename = translateSrc(state.dir, path.dirname(htmlfile), src);
554
648
  // Don't generate srcset file twice
@@ -563,7 +657,7 @@ async function generateSrcSet(state, htmlfile, originalImage, startSrc, startSrc
563
657
  else {
564
658
  // Write file
565
659
  if (!state.args.nowrite) {
566
- fs.writeFile(absoluteFilename, compressedImage.data);
660
+ await ((_a = state.vfs) !== null && _a !== void 0 ? _a : fsp).writeFile(absoluteFilename, compressedImage.data);
567
661
  }
568
662
  // Set new previous size to beat
569
663
  previousImageSize = compressedImage.data.length;
@@ -707,6 +801,7 @@ async function setImageSize(state, htmlfile, img, image) {
707
801
  throw new Error(`Unexpected issue when resolving image size "${image.src}"`);
708
802
  }
709
803
  export async function optimize(state, include, exclude) {
804
+ var _a;
710
805
  const glob = include ? [include] : ['**/*.{htm,html}'];
711
806
  if (exclude)
712
807
  glob.push('!' + exclude);
@@ -714,6 +809,7 @@ export async function optimize(state, include, exclude) {
714
809
  // Sequential async
715
810
  for (const file of paths) {
716
811
  await analyse(state, file);
812
+ (_a = state.onAnalysedFile) === null || _a === void 0 ? void 0 : _a.call(state, file);
717
813
  }
718
814
  }
719
815
  async function processTag(state, file, $, tag, attribute_to_log, processor, theFold, appendToBody) {
@@ -754,3 +850,14 @@ async function processTag(state, file, $, tag, attribute_to_log, processor, theF
754
850
  spinnerImg.succeed();
755
851
  }
756
852
  }
853
+ const isExternalImage = (content, external) => !isLocal(content) &&
854
+ isIncluded(content, external.src_include, external.src_exclude);
855
+ async function externalImage(content, state, htmlfile) {
856
+ const { process } = state.options.image.external;
857
+ if (process === 'download')
858
+ // Download external image for local processing
859
+ return await downloadExternalImage(state, htmlfile, content);
860
+ if (typeof process === 'function')
861
+ // Custom processing for external image
862
+ return await process(content);
863
+ }
@@ -1,12 +1,12 @@
1
1
  import * as path from 'path';
2
- import * as fs from 'fs/promises';
2
+ import * as fsp from 'fs/promises';
3
3
  import { hashSync as hasha } from 'hasha';
4
4
  import { fileTypeFromBuffer } from 'file-type';
5
5
  import { addToCache, getFromCache } from '../cache.js';
6
6
  import { parse } from '../utils/cache-control-parser.js';
7
7
  import '../utils/polyfill-fetch.js';
8
8
  export async function downloadExternalImage(state, htmlfile, href) {
9
- var _a, _b, _c, _d, _e;
9
+ var _a, _b, _c, _d, _e, _f;
10
10
  const hash = hasha(href, {
11
11
  algorithm: 'md5',
12
12
  });
@@ -97,6 +97,6 @@ export async function downloadExternalImage(state, htmlfile, href) {
97
97
  throw new Error('Unknown image format');
98
98
  const htmlFolder = path.dirname(htmlfile);
99
99
  const filename = path.relative(path.join(state.dir, htmlFolder), path.join(state.dir, `_jampack/${contentHash}.${ext}`));
100
- await fs.writeFile(path.join(state.dir, htmlFolder, filename), buffer);
100
+ await ((_f = state.vfs) !== null && _f !== void 0 ? _f : fsp).writeFile(path.join(state.dir, htmlFolder, filename), buffer);
101
101
  return filename;
102
102
  }
package/dist/state.d.ts CHANGED
@@ -29,6 +29,8 @@ export declare class GlobalState {
29
29
  installed_dependencies: Set<string>;
30
30
  summary: Summary;
31
31
  summaryByExtension: Record<string, Summary>;
32
+ vfs?: typeof import('fs/promises');
33
+ onAnalysedFile?: (file: string) => void;
32
34
  reportIssue(sourceFile: string, issue: Issue): void;
33
35
  reportSummary(r: ReportItem): void;
34
36
  }
@@ -1,12 +1,14 @@
1
- import * as fs from 'fs/promises';
1
+ import * as fsp from 'fs/promises';
2
2
  import * as path from 'path';
3
3
  import { createRequire } from 'node:module';
4
4
  const require = createRequire(import.meta.url);
5
5
  export async function install_dependency(state, html_file, options, appendToBody) {
6
+ var _a;
6
7
  const path_html = path.dirname('/' + html_file);
7
8
  const folder = `/_jampack/${options.destination.folder_name}`;
8
9
  const src_filename = options.source.filename;
9
10
  const url_loader = `${folder}/loader.js`;
11
+ const fs = (_a = state.vfs) !== null && _a !== void 0 ? _a : fsp;
10
12
  // Install dependency in /_jampack if not done yet
11
13
  if (!state.installed_dependencies.has(options.source.npm_package_name)) {
12
14
  const quickLinkDestination = path.join(state.dir, folder, src_filename);
@@ -17,7 +19,12 @@ export async function install_dependency(state, html_file, options, appendToBody
17
19
  await fs.writeFile(path_loader, code_loader);
18
20
  // Write quicklink code
19
21
  const source = require.resolve(`${options.source.npm_package_name}${options.source.absolute_path_to_file}/${src_filename}`);
20
- await fs.copyFile(source, quickLinkDestination);
22
+ if (state.vfs) {
23
+ await state.vfs.writeFile(quickLinkDestination, await fsp.readFile(source));
24
+ }
25
+ else {
26
+ await fs.copyFile(source, quickLinkDestination);
27
+ }
21
28
  state.installed_dependencies.add(options.source.npm_package_name);
22
29
  }
23
30
  // Add custom code to the end of body if not done yet
@@ -1,5 +1,6 @@
1
1
  import { FileExtension, MimeType } from 'file-type';
2
2
  import { ImageFormat } from '../compressors/images.js';
3
+ import { GlobalState } from '../state.js';
3
4
  type ImageMeta = {
4
5
  width: number | undefined;
5
6
  height: number | undefined;
@@ -11,13 +12,14 @@ type ImageMeta = {
11
12
  * File extension, mime and data are loaded only on demand, then cached.
12
13
  */
13
14
  export declare class Resource {
15
+ private state;
14
16
  readonly src: string;
15
17
  readonly filePathAbsolute: string;
16
18
  private ext;
17
19
  private mime;
18
20
  private data;
19
21
  private image_meta;
20
- constructor(src: string, filePathAbsolute: string);
22
+ constructor(state: GlobalState, src: string, filePathAbsolute: string);
21
23
  getData(): Promise<Buffer>;
22
24
  getImageMeta(): Promise<ImageMeta | null | undefined>;
23
25
  getLen(): Promise<number>;
@@ -25,9 +27,8 @@ export declare class Resource {
25
27
  getImageFormat(): Promise<ImageFormat | undefined>;
26
28
  getMime(): Promise<MimeType | 'image/svg+xml'>;
27
29
  private loadFileType;
28
- static loadResource(projectRoot: string, relativeFile: string, src: string): Promise<Resource | undefined>;
30
+ static loadResource(state: GlobalState, relativeFile: string, src: string): Promise<Resource | undefined>;
29
31
  }
30
32
  export declare function isLocal(src: string): boolean;
31
- export declare function fileExists(path: string): Promise<boolean>;
32
33
  export declare function translateSrc(projectRoot: string, htmlRelativePath: string, src: string): string;
33
34
  export {};
@@ -1,6 +1,6 @@
1
1
  import * as url from 'url';
2
2
  import * as path from 'path';
3
- import * as fs from 'fs/promises';
3
+ import * as fsp from 'fs/promises';
4
4
  import { fileTypeFromBuffer } from 'file-type';
5
5
  import sharp from 'sharp';
6
6
  import { AllImageFormat } from '../compressors/images.js';
@@ -8,13 +8,15 @@ import { AllImageFormat } from '../compressors/images.js';
8
8
  * File extension, mime and data are loaded only on demand, then cached.
9
9
  */
10
10
  export class Resource {
11
- constructor(src, filePathAbsolute) {
11
+ constructor(state, src, filePathAbsolute) {
12
+ this.state = state;
12
13
  this.src = src;
13
14
  this.filePathAbsolute = filePathAbsolute;
14
15
  }
15
16
  async getData() {
17
+ var _a;
16
18
  if (this.data === undefined) {
17
- this.data = await fs.readFile(this.filePathAbsolute);
19
+ this.data = await ((_a = this.state.vfs) !== null && _a !== void 0 ? _a : fsp).readFile(this.filePathAbsolute);
18
20
  }
19
21
  return this.data;
20
22
  }
@@ -98,7 +100,7 @@ export class Resource {
98
100
  throw new Error(`Unknown file type "${this.src}"`);
99
101
  }
100
102
  }
101
- static async loadResource(projectRoot, relativeFile, src) {
103
+ static async loadResource(state, relativeFile, src) {
102
104
  if (!isLocal(src)) {
103
105
  throw new Error('src should be local');
104
106
  }
@@ -106,10 +108,10 @@ export class Resource {
106
108
  if (!u.pathname) {
107
109
  throw new Error(`Invalid src format "${src}"`);
108
110
  }
109
- const relativePath = path.join(projectRoot, src.startsWith('/') ? '' : path.dirname(relativeFile), u.pathname);
111
+ const relativePath = path.join(state.dir, src.startsWith('/') ? '' : path.dirname(relativeFile), u.pathname);
110
112
  let absolutePath = path.resolve(relativePath);
111
- if (await fileExists(absolutePath)) {
112
- return new Resource(src, absolutePath);
113
+ if (await fileExists(state, absolutePath)) {
114
+ return new Resource(state, src, absolutePath);
113
115
  }
114
116
  return undefined;
115
117
  }
@@ -118,9 +120,10 @@ export function isLocal(src) {
118
120
  const u = url.parse(src);
119
121
  return !u.host;
120
122
  }
121
- export async function fileExists(path) {
123
+ async function fileExists(state, path) {
124
+ var _a;
122
125
  try {
123
- await fs.stat(path);
126
+ await ((_a = state.vfs) !== null && _a !== void 0 ? _a : fsp).stat(path);
124
127
  }
125
128
  catch (e) {
126
129
  return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@divriots/jampack",
3
- "version": "0.32.0",
3
+ "version": "0.33.0",
4
4
  "cache-version": {
5
5
  "img": "v1",
6
6
  "img-ext": "v1"
@@ -60,18 +60,17 @@
60
60
  "tslib": "^2.6.2",
61
61
  "typescript": "^5.4.5"
62
62
  },
63
+ "engines": {
64
+ "node": ">=14.0.0"
65
+ },
66
+ "bugs": "https://github.com/divriots/jampack/issues",
67
+ "keywords": [],
68
+ "types": "dist/index.d.ts",
63
69
  "scripts": {
64
70
  "watch": "pnpm build --watch",
65
71
  "try": "shx rm -fr demo && cp -R demo_drc demo && node ./dist/index.js ./demo --nocache",
66
72
  "build": "shx rm -rf dist && tsc -b",
67
73
  "lint": "eslint . --ext .ts --config .eslintrc",
68
- "prepublishOnly": "pnpm build",
69
74
  "cleanAllDotJampack": "find -s . | grep '.jampack$' | xargs rm -fr"
70
- },
71
- "engines": {
72
- "node": ">=14.0.0"
73
- },
74
- "bugs": "https://github.com/divriots/jampack/issues",
75
- "keywords": [],
76
- "types": "dist/index.d.ts"
77
- }
75
+ }
76
+ }