UNPKG

convert-svg-core

Version:

Supports converting SVG into another format using headless Chromium

346 lines 18.1 kB
import { type Browser, type LaunchOptions, type WaitForOptions } from "puppeteer-core"; import type { IProvider } from "./provider.js"; /** * Converts SVG to another format using a headless Chromium instance. * * When an {@link IConverter} is created it must either be passed an existing {@link Browser} instance via * {@link IConverterOptions#browser} or {@link IConverterLaunchOptions} via {@link IConverterOptions#launch} so that a * browser instance can be created or connected; otherwise it will fail to be created. * * If an existing {@link Browser} instance is being used you may want to also consider what happens if/when the * {@link IConverter} is closed (e.g. via {@link #close}) as the default behavior is to close the browser and all open * pages, even those not opened by the {@link IConverter}. It can instead be instructed to either disconnect from the * browser process or do nothing at all via {@link IConverterOptions#closeBehavior}. * * Due to constraints within Chromium, the SVG input is first written to a temporary HTML file and then navigated to. * This is because the default page for Chromium is using the `chrome` protocol so cannot load externally referenced * files (e.g. that use the `file` protocol). Each invocation of {@link #convert} or {@link #convertFile} open their own * {@link Page} and create their own temporary files to avoid conflicts with other asynchronous invocations, which is * closed and deleted respectively once finished. This allows a single {@link IConverter} to safely process these calls * concurrently. * * An {@link IConverter} uses its own {@link BrowserContext} to open each new {@link Page}. This ensures that the pages * are isolated and that they can be closed by the {@link IConverter} accordingly. * * It's also the responsibility of the caller to ensure that all {@link IConverter} instances are closed before the * process exits. */ export interface IConverter<ConvertOptions extends IConverterConvertOptions, ConvertOptionsParsed extends IConverterConvertOptionsParsed> { /** * Whether this {@link IConverter} has been closed. */ readonly closed: boolean; /** * The {@link IProvider} for this {@link IConverter}. */ readonly provider: IProvider<ConvertOptions, ConvertOptionsParsed>; /** * Closes this {@link IConverter}. * * What happens when the {@link IConverter} closes depends entirely on which {@link IConverterCloseBehavior} is being * used. The default behaviour is `"close"` but this may have been changed via {@link IConverterOptions#closeBehavior} * when this {@link IConverter} was created. * * Regardless of the behavior above, any temporary files that may have been created by this {@link IConverter} that * have not yet been deleted will be deleted now. * * Once closed, this {@link IConverter} should be discarded and a new one created, as and when needed. * * An error will occur if any problem arises while performing the closing behavior, where applicable. */ close(): Promise<void>; /** * Converts the specified `input` SVG into another format using the `options` provided. * * `input` can either be an SVG buffer or string. * * If the width and/or height cannot be derived from `input`; then they must be provided via their corresponding * options. This method attempts to derive the dimensions from `input` via any `width`/`height` attributes or its * calculated `viewBox` attribute. * * Only standard SVG element attributes (excl. event attributes) are allowed, and others are stripped from the SVG * before being converted. This includes deprecated attributes unless the `allowDeprecatedAttributes` option is * disabled. This is primarily for security purposes to ensure that malicious code cannot be injected. * * This method is resolved with the converted output buffer. * * An error will occur if this {@link IConverter} has been closed, both the `baseFile` and `baseUrl` options have been * provided, `input` does not contain an SVG element, or no `width` and/or `height` options were provided and this * information could not be derived from `input`. * * @param input The SVG input to be converted to another format. * @param options The options to be used. * @return The converted output buffer. */ convert(input: Buffer | string, options?: ConvertOptions): Promise<Buffer>; /** * Converts the SVG file at the specified path into another format using the `options` provided and writes it to the * output file. * * The output file is derived from `inputFilePath` unless the `outputFilePath` option is specified. * * If the width and/or height cannot be derived from the input file, then they must be provided via their * corresponding options. This method attempts to derive the dimensions from the input file via any `width`/`height` * attributes or its calculated `viewBox` attribute. * * Only standard SVG element attributes (excl. event attributes) are allowed, and others are stripped from the SVG * before being converted. This includes deprecated attributes unless the `allowDeprecatedAttributes` option is * disabled. This is primarily for security purposes to ensure that malicious code cannot be injected. * * This method is resolved with the path of the converted output file for reference. * * An error will occur if this {@link IConverter} has been closed, both the `baseFile` and `baseUrl` options have been * provided, the input file does not contain an SVG element, no `width` and/or `height` options were provided and this * information could not be derived from an input file, or a problem arises while reading the input file or writing * the output file. * * @param inputFilePath The path of the SVG file to be converted to another file format. * @param options The options to be used. * @return The output file path. */ convertFile(inputFilePath: string, options?: IConverterConvertFileOptions<ConvertOptions>): Promise<string>; } /** * The options that can be used to construct an implementation of {@link IConverter}. */ export interface IConverterOptions<ConvertOptions extends IConverterConvertOptions, ConvertOptionsParsed extends IConverterConvertOptionsParsed> { /** * An existing {@link Browser} instance provided by `puppeteer-core` that is used to create a {@link BrowserContext} * to open each new {@link Page} to capture a screenshot of an SVG to convert it into another format. If specified, * {@link #launch} will be ignored. * * For context; each {@link IConverter} instance uses their own {@link BrowserContext} to open each new {@link Page}. * This ensures that the pages are isolated and that they can be closed by the {@link IConverter} accordingly. A * {@linl Page} is opened for each invocation of {@link IConverter#convert} and {@link IConverter#convertFile} and * closed once finished. If the {@link IConverter} is closed (e.g. via {@link IConverter#close}), any pages currently * open due to ongoing invocations of those methods will be closed immediately and will likely result in them * rejecting. */ browser?: Browser; /** * The behavior when the {@link IConverter} is closed (e.g. via {@link IConverter#close}), which may be one of the * following: * * - `"close"` - Calls {@link Browser#close}, effectively closing the browser and therefore all open pages, even those * not opened by the {@link IConverter} in the scenario that a shared browser instance or connection is being used. * This is the default behavior as it typically makes most sense for those wanting to just let the `convert-svg-*` * package to manage the browser resources. * - `"disconnect"` - Calls {@link BrowserContext#close} and {@link Browser#disconnect}, effectively closing any pages * opened by the {@link IConverter} and disconnecting from the browser, keeping the browser process running and any * other pages created outside the {@link IConverter} open. * - `"none"` - Calls {@link BrowserContext#close}, effectively closing any pages opened by the {@link IConverter} but * not doing anything with the browser. This could potentially result in a browser instance running that cannot be * accessed to close depending on what was responsible for creating or connecting to the browser. * * Care should be taken when specifying this option that the consequences are fully understood as well as the shift in * the responsibilities to the caller to ensure that resources are managed accordingly. * * @defaultValue "close" */ closeBehavior?: IConverterCloseBehavior; /** * The options that are to be passed directly to `puppeteer-core` when launching a new {@link Browser} that is used to * create a {@link BrowserContext} to open each new {@link Page} to capture a screenshot of an SVG to convert it into * another format. Ignored if {@link #browser} is also specified. * * For context; each {@link IConverter} instance uses their own {@link BrowserContext} to open each new {@link Page}. * This ensures that the pages are isolated and that they can be closed by the {@link IConverter} accordingly. A * {@linl Page} is opened for each invocation of {@link IConverter#convert} and {@link IConverter#convertFile} and * closed once finished. If the {@link IConverter} is closed (e.g. via {@link IConverter#close}), any pages currently * open due to ongoing invocations of those methods will be closed immediately and will likely result in them * rejecting. */ launch?: IConverterLaunchOptions; /** * The options that are to be passed directly to `puppeteer-core` when populating a {@link Page} with the SVG * contents. * * For context; each {@link IConverter} instance uses their own {@link BrowserContext} to open each new {@link Page}. * This ensures that the pages are isolated and that they can be closed by the {@link IConverter} accordingly. A * {@linl Page} is opened for each invocation of {@link IConverter#convert} and {@link IConverter#convertFile} and * closed once finished. If the {@link IConverter} is closed (e.g. via {@link IConverter#close}), any pages currently * open due to ongoing invocations of those methods will be closed immediately and will likely result in them * rejecting. */ page?: WaitForOptions; /** * The {@link IProvider} to be used. */ provider: IProvider<ConvertOptions, ConvertOptionsParsed>; } /** * The behavior when a {@link IConverter} is closed (e.g. via {@link IConverter#close}), which may be one of the * following: * * - `"close"` - Calls {@link Browser#close}, effectively closing the browser and therefore all open pages, even those * not opened by the {@link IConverter} in the scenario that a shared browser instance or connection is being used. * - `"disconnect"` - Calls {@link BrowserContext#close} and {@link Browser#disconnect}, effectively closing any pages * opened by the {@link IConverter} and disconnecting from the browser, keeping the browser process running and any * other pages created outside the {@link IConverter} open. * - `"none"` - Calls {@link BrowserContext#close}, effectively closing any pages opened by the {@link IConverter} but * not doing anything with the browser. This could potentially result in a browser instance running that cannot be * accessed to close depending on what was responsible for creating or connecting to the browser. */ export type IConverterCloseBehavior = "close" | "disconnect" | "none"; /** * The options that can be passed to {@link IConverter#convert}. */ export interface IConverterConvertOptions { /** * Whether deprecated SVG element attributes should be retained in the SVG during conversion. * * @defaultValue true */ allowDeprecatedAttributes?: boolean; /** * The background color to be used to fill transparent regions within the SVG. If omitted, the {@link IProvider} will * determine the default background color. */ background?: string; /** * The path of the file to be converted into a file URL to use for all relative URLs contained within the SVG. Cannot * be used in conjunction with {@link #baseUrl}. */ baseFile?: string; /** * The base URL to use for all relative URLs contained within the SVG. Cannot be used in conjunction with * {@link #baseFile}. */ baseUrl?: string; /** * The height of the output to be generated. If omitted, an attempt will be made to derive the height from the SVG * input. */ height?: number | string; /** * The type of rounding to be applied to the width and height, which may be one of the following: * * - `"ceil"` - Values are rounded using `Math.ceil`. * - `"floor"` - Values are rounded using `Math.floor`. * - `"round"` - Values are rounded using `Math.round`. The default rounding used, if omitted. * * @defaultValue "round" */ rounding?: IConverterRounding; /** * The scale to be applied to the width and height (either specified as options or derived). * * @defaultValue 1 */ scale?: number; /** * The width of the output to be generated. If omitted, an attempt will be made to derive the width from the SVG * input. */ width?: number | string; } /** * The options that can be passed to {@link IConverter#convert} after being parsed. */ export interface IConverterConvertOptionsParsed { /** * Whether deprecated SVG element attributes should be retained in the SVG during conversion. */ allowDeprecatedAttributes: boolean; /** * The background color to be used to fill transparent regions within the SVG. If omitted, the {@link IProvider} will * determine the default background color. */ background?: string; /** * The base URL to use for all relative URLs contained within the SVG. */ baseUrl: string; /** * The height of the output to be generated. If omitted, an attempt will be made to derive the height from the SVG * input. */ height?: number; /** * The type of rounding to be applied to the width and height, which may be one of the following: * * - `"ceil"` - Values are rounded using `Math.ceil`. * - `"floor"` - Values are rounded using `Math.floor`. * - `"round"` - Values are rounded using `Math.round`. */ rounding: IConverterRounding; /** * The scale to be applied to the width and height (either specified as options or derived). */ scale: number; /** * The width of the output to be generated. If omitted, an attempt will be made to derive the width from the SVG * input. */ width?: number; } /** * The options that can be passed to {@link IConverter#convertFile}. */ export type IConverterConvertFileOptions<ConvertOptions extends IConverterConvertOptions> = ConvertOptions & { /** * The path of the file to which the output should be written to. By default, this will be derived from the input file * path. */ outputFilePath?: string; }; /** * The options that can be passed to {@link IConverter#convertFile} after being parsed. */ export type IConverterConvertFileOptionsParsed<ConvertOptionsParsed extends IConverterConvertOptionsParsed> = ConvertOptionsParsed & { /** * The path of the file to which the output should be written to. */ outputFilePath: string; }; /** * TODO: Document */ export type IConverterLaunchOptions = Omit<LaunchOptions, "executablePath"> & { /** * TODO: Document * * @param options * @return */ executablePath?: string | ((options: LaunchOptions) => string); }; /** * The type of rounding to be applied to the width and height during a conversion, which may be one of the following: * * - `"ceil"` - Values are rounded using `Math.ceil`. * - `"floor"` - Values are rounded using `Math.floor`. * - `"round"` - Values are rounded using `Math.round`. */ export type IConverterRounding = "ceil" | "floor" | "round"; /** * An implementation of {@link IConverter}. */ export declare class Converter<ConvertOptions extends IConverterConvertOptions, ConvertOptionsParsed extends IConverterConvertOptionsParsed> implements IConverter<ConvertOptions, ConvertOptionsParsed> { #private; /** * Creates an instance of {@link Converter} using the `options` provided. * * A {@link BrowserContext} is created from the either {@link IConverterOptions#browser}, if specified, or a new * {@link Browser} instance launched using {@link IConverterOptions#launch}. * * An error will occur if neither of the above options is specified. * * @param options The options to be used. * @return A newly created {@link Converter} instance. */ static create<ConvertOptions extends IConverterConvertOptions, ConvertOptionsParsed extends IConverterConvertOptionsParsed>(options: IConverterOptions<ConvertOptions, ConvertOptionsParsed>): Promise<Converter<ConvertOptions, ConvertOptionsParsed>>; /** * TODO: Document * * @return */ static parseEnvLaunchOptions(): IConverterLaunchOptions | undefined; private constructor(); convert(input: Buffer | string, options?: ConvertOptions): Promise<Buffer>; convertFile(inputFilePath: string, options?: IConverterConvertFileOptions<ConvertOptions>): Promise<string>; close(): Promise<void>; get closed(): boolean; get provider(): IProvider<ConvertOptions, ConvertOptionsParsed>; } //# sourceMappingURL=converter.d.ts.map