UNPKG

@compdfkit_pdf_sdk/react_native

Version:

ComPDFKit for React Native is a comprehensive SDK that allows you to quickly add PDF functionality to Android, iOS, and React Native applications.

231 lines (213 loc) 7.44 kB
import { HexColor } from "../configuration/CPDFOptions"; export type CPDFWatermarkType = "text" | "image"; export type CPDFWatermarkVerticalAlignment = "top" | "center" | "bottom"; export type CPDFWatermarkHorizontalAlignment = "left" | "center" | "right"; export type CPDFWatermark = { index: number; type: CPDFWatermarkType; pages: number[]; imagePath: string; isImageExported: boolean; textContent?: string; textColor?: HexColor; fontSize?: number; scale?: number; rotation?: number; opacity?: number; verticalAlignment?: CPDFWatermarkVerticalAlignment; horizontalAlignment?: CPDFWatermarkHorizontalAlignment; verticalOffset?: number; horizontalOffset?: number; isFront?: boolean; isTilePage?: boolean; horizontalSpacing?: number; verticalSpacing?: number; }; export type NativeWatermarkPayload = { index?: unknown; type?: unknown; text_content?: unknown; image_path?: unknown; is_image_exported?: unknown; text_color?: unknown; font_size?: unknown; scale?: unknown; rotation?: unknown; opacity?: unknown; vertical_alignment?: unknown; horizontal_alignment?: unknown; vertical_offset?: unknown; horizontal_offset?: unknown; pages?: unknown; is_front?: unknown; is_tile_page?: unknown; horizontal_spacing?: unknown; vertical_spacing?: unknown; }; export type CPDFWatermarkPatch = Partial<CPDFWatermark>; function asNumber(value: unknown, fallback: number): number { return typeof value === "number" && Number.isFinite(value) ? value : fallback; } function asPositiveNumber(value: unknown, fallback: number): number { return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback; } function asBoolean(value: unknown, fallback: boolean): boolean { return typeof value === "boolean" ? value : fallback; } function asString(value: unknown, fallback: string): string { return typeof value === "string" ? value : fallback; } function parsePages(value: unknown): number[] { if (Array.isArray(value)) { return value.filter((page): page is number => Number.isInteger(page)); } if (typeof value !== "string" || value.trim().length === 0) { return []; } const pages: number[] = []; for (const part of value.split(",")) { const trimmed = part.trim(); if (trimmed.includes("-")) { const [startRaw, endRaw] = trimmed.split("-"); const start = Number(startRaw); const end = Number(endRaw); if (Number.isInteger(start) && Number.isInteger(end) && end >= start) { for (let page = start; page <= end; page += 1) { pages.push(page); } } continue; } const page = Number(trimmed); if (Number.isInteger(page)) { pages.push(page); } } return pages; } function serializePages(pages: number[]): string { return pages.join(","); } function normalizeWatermark(watermark: CPDFWatermark): CPDFWatermark { return { index: watermark.index ?? -1, type: watermark.type, pages: watermark.pages ?? [], imagePath: watermark.imagePath ?? "", isImageExported: watermark.isImageExported ?? false, textContent: watermark.textContent ?? "", textColor: watermark.textColor ?? "#000000", fontSize: asPositiveNumber(watermark.fontSize, 24), scale: watermark.scale ?? 1, rotation: watermark.rotation ?? 45, opacity: watermark.opacity ?? 1, verticalAlignment: watermark.verticalAlignment ?? "center", horizontalAlignment: watermark.horizontalAlignment ?? "center", verticalOffset: watermark.verticalOffset ?? 0, horizontalOffset: watermark.horizontalOffset ?? 0, isFront: watermark.isFront ?? true, isTilePage: watermark.isTilePage ?? false, horizontalSpacing: watermark.horizontalSpacing ?? 0, verticalSpacing: watermark.verticalSpacing ?? 0, }; } export function createTextWatermark( params: Omit<Partial<CPDFWatermark>, "type" | "imagePath" | "isImageExported"> & { textContent: string; pages: number[]; } ): CPDFWatermark { return normalizeWatermark({ ...params, index: params.index ?? -1, type: "text", imagePath: "", isImageExported: false, }); } export function createImageWatermark( params: Omit<Partial<CPDFWatermark>, "type" | "textContent" | "textColor" | "fontSize"> & { imagePath: string; pages: number[]; } ): CPDFWatermark { return normalizeWatermark({ ...params, index: params.index ?? -1, type: "image", textContent: "", textColor: "#000000", fontSize: 24, isImageExported: params.isImageExported ?? false, }); } export function copyWatermark( watermark: CPDFWatermark, patch: CPDFWatermarkPatch ): CPDFWatermark { return normalizeWatermark({ ...watermark, ...patch, }); } export function fromNativeWatermark(payload: NativeWatermarkPayload): CPDFWatermark { return normalizeWatermark({ index: asNumber(payload.index, -1), type: asString(payload.type, "text") === "image" ? "image" : "text", textContent: asString(payload.text_content, ""), imagePath: asString(payload.image_path, ""), isImageExported: asBoolean(payload.is_image_exported, false), textColor: asString(payload.text_color, "#000000") as HexColor, fontSize: asPositiveNumber(payload.font_size, 24), scale: asNumber(payload.scale, 1), rotation: asNumber(payload.rotation, 45), opacity: asNumber(payload.opacity, 1), verticalAlignment: asString(payload.vertical_alignment, "center") as CPDFWatermarkVerticalAlignment, horizontalAlignment: asString(payload.horizontal_alignment, "center") as CPDFWatermarkHorizontalAlignment, verticalOffset: asNumber(payload.vertical_offset, 0), horizontalOffset: asNumber(payload.horizontal_offset, 0), pages: parsePages(payload.pages), isFront: asBoolean(payload.is_front, true), isTilePage: asBoolean(payload.is_tile_page, false), horizontalSpacing: asNumber(payload.horizontal_spacing, 0), verticalSpacing: asNumber(payload.vertical_spacing, 0), }); } export function toNativeWatermark( watermark: CPDFWatermark, options: { allowEmptyImagePath?: boolean } = {} ): NativeWatermarkPayload { const normalized = normalizeWatermark(watermark); if (normalized.pages.length === 0) { throw new Error("Watermark pages cannot be empty."); } if (normalized.type === "text" && !normalized.textContent) { throw new Error("Text watermark textContent cannot be empty."); } if (normalized.type === "image" && !normalized.imagePath && !options.allowEmptyImagePath) { throw new Error("Image watermark imagePath cannot be empty."); } return { index: normalized.index, type: normalized.type, text_content: normalized.textContent, image_path: normalized.imagePath, is_image_exported: normalized.isImageExported, text_color: normalized.textColor, font_size: normalized.fontSize, scale: normalized.scale, rotation: normalized.rotation, opacity: normalized.opacity, vertical_alignment: normalized.verticalAlignment, horizontal_alignment: normalized.horizontalAlignment, vertical_offset: normalized.verticalOffset, horizontal_offset: normalized.horizontalOffset, pages: serializePages(normalized.pages), is_front: normalized.isFront, is_tile_page: normalized.isTilePage, horizontal_spacing: normalized.horizontalSpacing, vertical_spacing: normalized.verticalSpacing, }; }