polotno-node 3.1.3 → 3.3.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/lib/index.js CHANGED
@@ -1,121 +1,43 @@
1
1
  import puppeteerCore from 'puppeteer-core';
2
- import sparticuz from '@sparticuz/chromium';
3
2
  import os from 'os';
4
3
  import { createInstance as createInstanceImpl } from './instance.js';
5
- // TODO: that is a weird hack, but it works
6
- const chrome = sparticuz.default || sparticuz;
7
- const isMacOs = os.platform() === 'darwin';
8
- const isWindows = os.platform() === 'win32';
9
- // On non-Linux platforms use full puppeteer (bundles its own Chromium) instead
10
- // of @sparticuz/chromium. ESM imports are immutable, so resolve the variant via
11
- // a dynamic import. `puppeteer` is an optional peer on Linux servers, so the
12
- // import only runs where it's expected to be installed.
4
+ import { BUNDLED_CHROMIUM_PLATFORM, resolveBrowserArgs, resolveExecutablePath, } from './launch-options.js';
5
+ export { args } from './launch-options.js';
6
+ // Off the bundled chromium's platform, use full puppeteer — it brings its own
7
+ // Chromium. ESM imports are immutable, so resolve the variant via a dynamic
8
+ // import. `puppeteer` is an optional peer on Linux servers, so the import only
9
+ // runs where it's expected to be installed.
13
10
  let puppeteer = puppeteerCore;
14
- if (isMacOs || isWindows) {
11
+ if (os.platform() !== BUNDLED_CHROMIUM_PLATFORM) {
15
12
  puppeteer = (await import('puppeteer')).default;
16
13
  }
17
- export const args = [
18
- 'about:blank',
19
- '--disable-web-security',
20
- '--allow-file-access-from-files',
21
- '--allow-pre-commit-input',
22
- '--autoplay-policy=user-gesture-required',
23
- '--disable-background-networking',
24
- '--disable-background-timer-throttling',
25
- '--disable-backgrounding-occluded-windows',
26
- '--disable-breakpad',
27
- '--disable-component-extensions-with-background-pages',
28
- '--disable-client-side-phishing-detection',
29
- '--disable-component-update',
30
- '--disable-default-apps',
31
- '--disable-dev-shm-usage',
32
- '--proxy-server=direct://',
33
- '--proxy-bypass-list=*',
34
- '--disable-domain-reliability',
35
- '--disable-features=AudioServiceOutOfProcess,IsolateOrigins,site-per-process,Translate,BackForwardCache,AvoidUnnecessaryBeforeUnloadCheckSync,IntensiveWakeUpThrottling',
36
- '--disable-extensions',
37
- '--disable-hang-monitor',
38
- '--disable-ipc-flooding-protection',
39
- '--disable-notifications',
40
- '--disable-offer-store-unmasked-wallet-cards',
41
- '--disable-popup-blocking',
42
- '--disable-print-preview',
43
- '--disable-site-isolation-trials',
44
- '--disable-prompt-on-repost',
45
- '--disable-renderer-backgrounding',
46
- '--disable-setuid-sandbox',
47
- '--disable-speech-api',
48
- '--disable-sync',
49
- // Use srgb for identical output across Linux/macOS/Windows and to match how CSS colors/images are defined/assumed on the web.
50
- '--force-color-profile=srgb',
51
- '--hide-scrollbars',
52
- '--metrics-recording-only',
53
- '--mute-audio',
54
- '--no-default-browser-check',
55
- '--no-first-run',
56
- '--enable-automation',
57
- '--no-pings',
58
- '--no-sandbox',
59
- '--no-zygote',
60
- '--password-store=basic',
61
- '--allow-running-insecure-content',
62
- // Disable accessibility features to reduce resource usage and improve performance.
63
- '--disable-renderer-accessibility',
64
- // stable locale → font fallback/hyphenation
65
- '--lang=en-US',
66
- // this line breaks the rendering on most of OS
67
- // it doesn't allow creating of pages
68
- //'--use-gl=swiftshader',
69
- '--disable-gpu',
70
- '--use-mock-keychain',
71
- '--enable-blink-features=IdleDetection',
72
- '--intensive-wake-up-throttling-policy=0',
73
- '--font-render-hinting=none',
74
- '--ignore-gpu-blocklist',
75
- // don't use this flag, because it makes renderign less accurate
76
- // see https://community.polotno.com/c/ask/the-ability-to-exclude-args-from-minimal_args-in-polotno-node
77
- // '--disable-font-subpixel-positioning',
78
- '--text-rendering=geometricprecision',
79
- ].filter(Boolean);
80
- /**
81
- * Merge browser argument arrays, deduping by flag name (the part before `=`).
82
- * Later arrays take precedence on conflict.
83
- */
84
- function mergeArgs(...argArrays) {
85
- const argMap = new Map();
86
- for (const argArray of argArrays) {
87
- for (const arg of argArray) {
88
- const flagMatch = arg.match(/^(--[^=]+)/);
89
- const flagName = flagMatch ? flagMatch[1] : arg;
90
- argMap.set(flagName, arg);
91
- }
92
- }
93
- return Array.from(argMap.values());
94
- }
95
14
  const browserProps = {
96
- headless: 'new',
15
+ headless: true,
97
16
  // make large timeout, because some renders may take a lot of time
98
17
  // like large PDF or video render
99
18
  protocolTimeout: 60 * 60 * 1000,
100
19
  ignoreHTTPSErrors: true,
101
20
  };
102
- export async function createBrowser({ browserArgs = [], ...rest } = {}) {
21
+ export async function createBrowser(options = {}) {
22
+ // Both are resolved below, so neither may also reach the spread — a caller
23
+ // forwarding an unset env var (`executablePath:
24
+ // process.env.PUPPETEER_EXECUTABLE_PATH`) would overwrite the resolved path
25
+ // with `undefined` and leave puppeteer-core with no browser at all.
26
+ const { browserArgs, executablePath, ...rest } = options;
103
27
  return puppeteer.launch({
104
- args: mergeArgs(isWindows ? [] : chrome.args, args, browserArgs),
105
- defaultViewport: chrome.defaultViewport,
106
- executablePath: isMacOs || isWindows ? undefined : await chrome.executablePath(),
28
+ args: resolveBrowserArgs(options),
29
+ executablePath: await resolveExecutablePath(options),
107
30
  ...browserProps,
108
31
  ...rest,
109
32
  });
110
33
  }
111
- export const createInstance = async ({ key, url, useParallelPages, browserArgs = [], browser, requestInterceptor, useFontCache, } = {}) => {
34
+ export const createInstance = async (options = {}) => {
35
+ // Named here only because they shape the browser; everything else is passed
36
+ // straight through. Relisting each option by name is how `navigationTimeout`
37
+ // came to be declared, honoured downstream, and silently dropped in between.
38
+ const { browser, executablePath, browserArgs, ...rest } = options;
112
39
  return await createInstanceImpl({
113
- browser: browser || (await createBrowser({ browserArgs })),
114
- key,
115
- url,
116
- useParallelPages,
117
- browserArgs,
118
- requestInterceptor,
119
- useFontCache,
40
+ ...rest,
41
+ browser: browser || (await createBrowser({ browserArgs, executablePath })),
120
42
  });
121
43
  };
package/lib/instance.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { type FetchPolicy } from './ssrf-guard.js';
1
2
  declare global {
2
3
  interface Window {
3
4
  config?: any;
@@ -9,19 +10,24 @@ declare global {
9
10
  __polotnoWriteChunk?: (chunk: string) => void;
10
11
  }
11
12
  }
12
- export declare const createPage: (browser: any, url: any, requestInterceptor: any, useFontCache?: boolean) => Promise<any>;
13
+ export declare const guessExtension: (contentType: any, kind: any) => any;
14
+ export declare const prepareLocalMediaForVideoExport: (json: any, policy?: FetchPolicy) => Promise<{
15
+ json: any;
16
+ cleanup: () => Promise<void>;
17
+ }>;
18
+ export declare const createPage: (browser: any, url: any, requestInterceptor: any, useFontCache?: boolean, navigationTimeout?: number) => Promise<any>;
13
19
  export declare const run: (page: any, func: any, args: any) => Promise<any>;
14
20
  export declare const jsonToDataURL: (page: any, json: any, attrs: any) => Promise<any>;
15
21
  export declare const jsonToPDFDataURL: (page: any, json: any, attrs: any) => Promise<any>;
16
22
  export declare const jsonToBlob: (page: any, json: any, attrs: any) => Promise<any>;
17
- export declare const createInstance: ({ key, url, useParallelPages, browser, requestInterceptor, useFontCache, }?: {
23
+ export declare const createInstance: ({ key, url, useParallelPages, browser, requestInterceptor, useFontCache, navigationTimeout, }?: {
18
24
  key?: string;
19
25
  url?: string;
20
26
  useParallelPages?: boolean;
21
27
  browser?: any;
22
- browserArgs?: string[];
23
28
  requestInterceptor?: (request: any) => void;
24
29
  useFontCache?: boolean;
30
+ navigationTimeout?: number;
25
31
  }) => Promise<{
26
32
  close: () => Promise<void>;
27
33
  firstPage: any;