@sme.up/doc-alchemist 1.5.0-SNAPSHOT-20251126090326 → 1.5.0-SNAPSHOT-20251126145720

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.
@@ -11,6 +11,24 @@ const isPlainObject = (value) => {
11
11
  !Array.isArray(value) &&
12
12
  Object.prototype.toString.call(value) === "[object Object]");
13
13
  };
14
+ /**
15
+ * Properties of pdfmake document that should not be processed by adapters.
16
+ * These are configuration properties, not content.
17
+ */
18
+ const EXCLUDED_PROPERTIES = new Set([
19
+ "styles",
20
+ "defaultStyle",
21
+ "pageSize",
22
+ "pageMargins",
23
+ "pageOrientation",
24
+ "pageBreakBefore",
25
+ "info",
26
+ "permissions",
27
+ "compress",
28
+ "userPassword",
29
+ "ownerPassword",
30
+ "version",
31
+ ]);
14
32
  /**
15
33
  * Processes a document recursively, applying adapters to matching elements.
16
34
  *
@@ -63,7 +81,13 @@ const processDocument = async (element, adapters, context) => {
63
81
  // Recursively process all properties
64
82
  const processed = {};
65
83
  for (const [key, value] of Object.entries(element)) {
66
- processed[key] = await (0, exports.processDocument)(value, adapters, context);
84
+ // Skip excluded properties (don't process them recursively)
85
+ if (EXCLUDED_PROPERTIES.has(key)) {
86
+ processed[key] = value;
87
+ }
88
+ else {
89
+ processed[key] = await (0, exports.processDocument)(value, adapters, context);
90
+ }
67
91
  }
68
92
  return processed;
69
93
  }
@@ -80,22 +104,8 @@ const preProcessPdfMakeDocument = async (documentDefinition, context, registry)
80
104
  return Promise.resolve(documentDefinition);
81
105
  }
82
106
  else {
107
+ documentDefinition.images = documentDefinition.images || {};
83
108
  const processedDoc = (await registry?.process(documentDefinition, context));
84
- // Merge all first-level properties from pdfDocument
85
- // (excluding content, header, footer which are already processed)
86
- if (context.pdfDocument) {
87
- for (const [key, value] of Object.entries(context.pdfDocument)) {
88
- if (key === "content" || key === "header" || key === "footer") {
89
- continue;
90
- }
91
- if (value !== undefined && isPlainObject(value)) {
92
- processedDoc[key] = {
93
- ...(documentDefinition[key] || {}),
94
- ...value,
95
- };
96
- }
97
- }
98
- }
99
109
  return processedDoc;
100
110
  }
101
111
  };
@@ -1 +1 @@
1
- {"version":3,"file":"adapter-processor.js","sourceRoot":"","sources":["../../../../src/converters/pdf/pdfmake/adapter-processor.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n PdfMakeConverterContext,\n AdapterError,\n PdfmakeAdapter,\n AdapterRegistry,\n} from \"./pdfmake.types\";\nimport type { TDocumentDefinitions } from \"pdfmake/interfaces\";\n\n/**\n * Helper to check if a value is a plain object\n */\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n return (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n Object.prototype.toString.call(value) === \"[object Object]\"\n );\n};\n\n/**\n * Processes a document recursively, applying adapters to matching elements.\n *\n * @param element - The current element to process\n * @param adapters - Map of element types to their adapter functions\n * @param context - Current processing context\n * @returns The transformed element\n */\nexport const processDocument = async (\n element: unknown,\n adapters: Map<string, PdfmakeAdapter>,\n context: PdfMakeConverterContext,\n): Promise<unknown> => {\n // Handle null/undefined\n if (element == null) {\n return element;\n }\n try {\n // Handle arrays - process each item\n if (Array.isArray(element)) {\n return await Promise.all(\n element.map(item => processDocument(item, adapters, context)),\n );\n }\n\n // Handle plain objects\n if (isPlainObject(element)) {\n // Try to apply adapters based on element type\n const elementType = element.type as string | undefined;\n if (elementType && adapters.has(elementType)) {\n const adapter = adapters.get(elementType)!;\n element = await adapter(element, context);\n\n // After transformation, element might not be a plain object anymore\n if (!isPlainObject(element)) {\n return element;\n }\n }\n\n // Also try adapters based on properties (e.g., \"table\" property)\n for (const [key, adapter] of adapters.entries()) {\n // Skip type-based adapters already processed\n if (key === elementType) continue;\n\n // Apply adapter if it matches a property name\n if (key in element) {\n const transformed = await adapter(element, context);\n // Only accept transformation if adapter actually changed something\n if (transformed !== element) {\n element = transformed;\n // After transformation, element might not be a plain object anymore\n if (!isPlainObject(element)) {\n return element;\n }\n // Continue to apply other adapters (e.g., both header and footer)\n }\n }\n }\n\n // Recursively process all properties\n const processed: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(\n element as Record<string, unknown>,\n )) {\n processed[key] = await processDocument(value, adapters, context);\n }\n return processed;\n }\n\n // Primitive values - return as-is\n return element;\n } catch (err) {\n throw new AdapterError(err as string, element);\n }\n};\n\nexport const preProcessPdfMakeDocument = async (\n documentDefinition: TDocumentDefinitions,\n context: Partial<PdfMakeConverterContext>,\n registry?: AdapterRegistry,\n): Promise<TDocumentDefinitions> => {\n if (!registry) {\n return Promise.resolve(documentDefinition);\n } else {\n const processedDoc = (await registry?.process(\n documentDefinition,\n context,\n )) as TDocumentDefinitions;\n\n // Merge all first-level properties from pdfDocument\n // (excluding content, header, footer which are already processed)\n if (context.pdfDocument) {\n for (const [key, value] of Object.entries(context.pdfDocument)) {\n if (key === \"content\" || key === \"header\" || key === \"footer\") {\n continue;\n }\n if (value !== undefined && isPlainObject(value)) {\n (processedDoc as unknown as Record<string, unknown>)[key] = {\n ...(((documentDefinition as unknown as Record<string, unknown>)[\n key\n ] as object) || {}),\n ...value,\n };\n }\n }\n }\n\n return processedDoc;\n }\n};\n"]}
1
+ {"version":3,"file":"adapter-processor.js","sourceRoot":"","sources":["../../../../src/converters/pdf/pdfmake/adapter-processor.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n PdfMakeConverterContext,\n AdapterError,\n PdfmakeAdapter,\n AdapterRegistry,\n} from \"./pdfmake.types\";\nimport type { TDocumentDefinitions } from \"pdfmake/interfaces\";\n\n/**\n * Helper to check if a value is a plain object\n */\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n return (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n Object.prototype.toString.call(value) === \"[object Object]\"\n );\n};\n\n/**\n * Properties of pdfmake document that should not be processed by adapters.\n * These are configuration properties, not content.\n */\nconst EXCLUDED_PROPERTIES = new Set([\n \"styles\",\n \"defaultStyle\",\n \"pageSize\",\n \"pageMargins\",\n \"pageOrientation\",\n \"pageBreakBefore\",\n \"info\",\n \"permissions\",\n \"compress\",\n \"userPassword\",\n \"ownerPassword\",\n \"version\",\n]);\n\n/**\n * Processes a document recursively, applying adapters to matching elements.\n *\n * @param element - The current element to process\n * @param adapters - Map of element types to their adapter functions\n * @param context - Current processing context\n * @returns The transformed element\n */\nexport const processDocument = async (\n element: unknown,\n adapters: Map<string, PdfmakeAdapter>,\n context: PdfMakeConverterContext,\n): Promise<unknown> => {\n // Handle null/undefined\n if (element == null) {\n return element;\n }\n try {\n // Handle arrays - process each item\n if (Array.isArray(element)) {\n return await Promise.all(\n element.map(item => processDocument(item, adapters, context)),\n );\n }\n\n // Handle plain objects\n if (isPlainObject(element)) {\n // Try to apply adapters based on element type\n const elementType = element.type as string | undefined;\n if (elementType && adapters.has(elementType)) {\n const adapter = adapters.get(elementType)!;\n element = await adapter(element, context);\n\n // After transformation, element might not be a plain object anymore\n if (!isPlainObject(element)) {\n return element;\n }\n }\n\n // Also try adapters based on properties (e.g., \"table\" property)\n for (const [key, adapter] of adapters.entries()) {\n // Skip type-based adapters already processed\n if (key === elementType) continue;\n\n // Apply adapter if it matches a property name\n if (key in element) {\n const transformed = await adapter(element, context);\n // Only accept transformation if adapter actually changed something\n if (transformed !== element) {\n element = transformed;\n // After transformation, element might not be a plain object anymore\n if (!isPlainObject(element)) {\n return element;\n }\n // Continue to apply other adapters (e.g., both header and footer)\n }\n }\n }\n\n // Recursively process all properties\n const processed: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(\n element as Record<string, unknown>,\n )) {\n // Skip excluded properties (don't process them recursively)\n if (EXCLUDED_PROPERTIES.has(key)) {\n processed[key] = value;\n } else {\n processed[key] = await processDocument(value, adapters, context);\n }\n }\n return processed;\n }\n\n // Primitive values - return as-is\n return element;\n } catch (err) {\n throw new AdapterError(err as string, element);\n }\n};\n\nexport const preProcessPdfMakeDocument = async (\n documentDefinition: TDocumentDefinitions,\n context: Partial<PdfMakeConverterContext>,\n registry?: AdapterRegistry,\n): Promise<TDocumentDefinitions> => {\n if (!registry) {\n return Promise.resolve(documentDefinition);\n } else {\n documentDefinition.images = documentDefinition.images || {};\n\n const processedDoc = (await registry?.process(\n documentDefinition,\n context,\n )) as TDocumentDefinitions;\n\n return processedDoc;\n }\n};\n"]}
@@ -129,8 +129,21 @@ const objectToUrlAdapter = () => {
129
129
  exports.objectToUrlAdapter = objectToUrlAdapter;
130
130
  const imageAdapter = () => {
131
131
  return async (element, context) => {
132
- const adaptedElement = await (0, exports.objectToUrlAdapter)()(element, context);
133
- return (0, exports.urlToImageAdapter)()(adaptedElement, context);
132
+ try {
133
+ const adaptedElement = await (0, exports.objectToUrlAdapter)()(element, context);
134
+ return await (0, exports.urlToImageAdapter)()(adaptedElement, context);
135
+ }
136
+ catch (error) {
137
+ console.error(error);
138
+ const errorMessage = error.message;
139
+ const cause = error.cause;
140
+ const causeMessage = cause ? `\nCause: ${cause.message || cause}` : "";
141
+ return {
142
+ text: `Error loading image: ${errorMessage}${causeMessage}`,
143
+ fontSize: 10,
144
+ color: "#8B0000",
145
+ };
146
+ }
134
147
  };
135
148
  };
136
149
  exports.imageAdapter = imageAdapter;
@@ -1 +1 @@
1
- {"version":3,"file":"image-adapter.js","sourceRoot":"","sources":["../../../../src/converters/pdf/pdfmake/image-adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import { SmeupDataTree } from \"../../../types/data-structures/smeupDataTree\";\nimport {\n ContentImageExtension,\n ElementWithImageExtension,\n PdfMakeConverterContext,\n} from \"./pdfmake.types\";\n\nconst hasSmeupUrl = (element: unknown): boolean => {\n const image = (element as Record<string, unknown>)\n .image as ContentImageExtension;\n const url = image?.smeup?.url;\n return typeof url === \"string\" && url.length > 0;\n};\n\nfunction hasSmeupObject(element: unknown): boolean {\n const image = (element as Record<string, unknown>)\n .image as ContentImageExtension;\n const obj = image?.smeup?.obj;\n return typeof obj === \"object\" && obj !== null;\n}\n\n/**\n * Downloads an image from a URL and converts it to a data URL format.\n * Validates that the content-type is an image MIME type.\n *\n * @param url - The URL of the image to download\n * @param fetchData - Callback function to fetch the image data\n * @returns A data URL string in the format: data:image/jpeg;base64,<base64>\n * @throws If the download fails, content-type is not an image, or network error occurs\n */\nconst downloadImageAsDataUrl = async (\n url: string,\n fetchData: (url: string) => Promise<Response>,\n): Promise<string> => {\n const response = await fetchData(url);\n\n if (!response.ok) {\n throw new Error(\n `Failed to download image from ${url}: ${response.status} ${response.statusText}`,\n );\n }\n\n // Extract content-type from headers\n const contentType = response.headers.get(\"content-type\") || \"image/jpeg\";\n\n // Validate that content-type is an image\n if (!contentType.startsWith(\"image/\")) {\n throw new Error(\n `Invalid content-type for image: expected image/*, got ${contentType}`,\n );\n }\n\n // Get image data and convert to base64\n const arrayBuffer = await response.arrayBuffer();\n const base64 = Buffer.from(arrayBuffer).toString(\"base64\");\n\n return `data:${contentType};base64,${base64}`;\n};\n\n/**\n * Adapts a Smeup image structure to the PDFMake image format.\n *\n * This adapter function checks if the provided element contains an image with a smeup URL.\n * If so, it downloads the image using the fetchData callback from context, validates the\n * content-type, and transforms it into a data URL format that PDFMake can use.\n * The data URL is stored in context.pdfDocument.images to avoid redundancy when the same\n * image is referenced multiple times.\n * All properties of the original image except `smeup` are preserved.\n *\n * @returns An async function that takes an element and returns the adapted element for PDFMake,\n * or the original element if it does not contain a valid smeup image.\n * @throws If the context does not provide a fetchData function when the smeup image is used.\n * @throws If the image download fails or the content-type is not a valid image MIME type.\n */\nexport const urlToImageAdapter = () => {\n return async (\n element: unknown,\n context: PdfMakeConverterContext,\n ): Promise<ContentImageExtension> => {\n if (!hasSmeupUrl(element)) {\n return element as ContentImageExtension;\n }\n\n if (!context.fetchData) {\n throw new Error(\n \"fetchData function is required in context when the smeup image property is used\",\n );\n }\n\n const elementImage = element as { image: { smeup: { url: string } } };\n const url = elementImage.image.smeup.url;\n\n // Ensure pdfDocument exists in context\n if (!context.pdfDocument) {\n throw new Error(\n \"pdfDocument is required in context when the smeup image property is used\",\n );\n }\n\n // Initialize images dictionary if not present\n if (!context.pdfDocument.images) {\n context.pdfDocument.images = {};\n }\n\n // Download and cache the image only if not already present\n if (!context.pdfDocument.images[url]) {\n const dataUrl = await downloadImageAsDataUrl(url, context.fetchData);\n context.pdfDocument.images[url] = dataUrl;\n }\n\n // Extract all properties except 'smeup' from the image object\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { smeup, ...imageRest } = elementImage.image;\n\n return {\n ...elementImage,\n image: url,\n ...imageRest,\n };\n };\n};\n\nexport const objectToUrlAdapter = () => {\n return async (\n element: unknown,\n context: PdfMakeConverterContext,\n ): Promise<ElementWithImageExtension> => {\n if (!hasSmeupObject(element)) {\n return element as ElementWithImageExtension;\n }\n if (!context.getSmeupDataStructure || !context.damSvcEndpoint) {\n throw new Error(\n \"getSmeupDataStructure function and damSvcEndpoint prop are required in context when the smeup image obj property is used\",\n );\n } else {\n const elementImage = element as ElementWithImageExtension;\n const obj = elementImage.image.smeup?.obj;\n if (!obj || !obj.t || !obj.p || !obj.k) {\n throw new Error(\n \"Smeup object must have t, p, and k properties to build GET.PATH function\",\n );\n }\n const funToGetPATH = `F(TRE;JASER_12W;GET.PATH) 1(${obj.t};${obj.p};${obj.k})`;\n const dataTree = (await context.getSmeupDataStructure(\n funToGetPATH,\n )) as SmeupDataTree;\n if (dataTree.children?.length === 0) {\n throw new Error(`No data found for function ${funToGetPATH}`);\n } else {\n const pathNode = dataTree.children[0].value.replace(/\\\\/g, \"/\");\n const pathEncoded = encodeURIComponent(pathNode);\n const url = context.damSvcEndpoint + \"/\" + pathEncoded;\n\n // Extract all properties except 'smeup' from the image object\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { smeup, ...imageRest } = elementImage.image;\n\n return {\n ...elementImage,\n image: {\n smeup: {\n url,\n },\n ...imageRest,\n },\n };\n }\n }\n };\n};\n\nexport const imageAdapter = () => {\n return async (\n element: unknown,\n context: PdfMakeConverterContext,\n ): Promise<ContentImageExtension> => {\n const adaptedElement = await objectToUrlAdapter()(element, context);\n return urlToImageAdapter()(adaptedElement, context);\n };\n};\n"]}
1
+ {"version":3,"file":"image-adapter.js","sourceRoot":"","sources":["../../../../src/converters/pdf/pdfmake/image-adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import { SmeupDataTree } from \"../../../types/data-structures/smeupDataTree\";\nimport {\n ContentImageExtension,\n ElementWithImageExtension,\n PdfMakeConverterContext,\n} from \"./pdfmake.types\";\n\nconst hasSmeupUrl = (element: unknown): boolean => {\n const image = (element as Record<string, unknown>)\n .image as ContentImageExtension;\n const url = image?.smeup?.url;\n return typeof url === \"string\" && url.length > 0;\n};\n\nfunction hasSmeupObject(element: unknown): boolean {\n const image = (element as Record<string, unknown>)\n .image as ContentImageExtension;\n const obj = image?.smeup?.obj;\n return typeof obj === \"object\" && obj !== null;\n}\n\n/**\n * Downloads an image from a URL and converts it to a data URL format.\n * Validates that the content-type is an image MIME type.\n *\n * @param url - The URL of the image to download\n * @param fetchData - Callback function to fetch the image data\n * @returns A data URL string in the format: data:image/jpeg;base64,<base64>\n * @throws If the download fails, content-type is not an image, or network error occurs\n */\nconst downloadImageAsDataUrl = async (\n url: string,\n fetchData: (url: string) => Promise<Response>,\n): Promise<string> => {\n const response = await fetchData(url);\n\n if (!response.ok) {\n throw new Error(\n `Failed to download image from ${url}: ${response.status} ${response.statusText}`,\n );\n }\n\n // Extract content-type from headers\n const contentType = response.headers.get(\"content-type\") || \"image/jpeg\";\n\n // Validate that content-type is an image\n if (!contentType.startsWith(\"image/\")) {\n throw new Error(\n `Invalid content-type for image: expected image/*, got ${contentType}`,\n );\n }\n\n // Get image data and convert to base64\n const arrayBuffer = await response.arrayBuffer();\n const base64 = Buffer.from(arrayBuffer).toString(\"base64\");\n\n return `data:${contentType};base64,${base64}`;\n};\n\n/**\n * Adapts a Smeup image structure to the PDFMake image format.\n *\n * This adapter function checks if the provided element contains an image with a smeup URL.\n * If so, it downloads the image using the fetchData callback from context, validates the\n * content-type, and transforms it into a data URL format that PDFMake can use.\n * The data URL is stored in context.pdfDocument.images to avoid redundancy when the same\n * image is referenced multiple times.\n * All properties of the original image except `smeup` are preserved.\n *\n * @returns An async function that takes an element and returns the adapted element for PDFMake,\n * or the original element if it does not contain a valid smeup image.\n * @throws If the context does not provide a fetchData function when the smeup image is used.\n * @throws If the image download fails or the content-type is not a valid image MIME type.\n */\nexport const urlToImageAdapter = () => {\n return async (\n element: unknown,\n context: PdfMakeConverterContext,\n ): Promise<ContentImageExtension> => {\n if (!hasSmeupUrl(element)) {\n return element as ContentImageExtension;\n }\n\n if (!context.fetchData) {\n throw new Error(\n \"fetchData function is required in context when the smeup image property is used\",\n );\n }\n\n const elementImage = element as { image: { smeup: { url: string } } };\n const url = elementImage.image.smeup.url;\n\n // Ensure pdfDocument exists in context\n if (!context.pdfDocument) {\n throw new Error(\n \"pdfDocument is required in context when the smeup image property is used\",\n );\n }\n\n // Initialize images dictionary if not present\n if (!context.pdfDocument.images) {\n context.pdfDocument.images = {};\n }\n\n // Download and cache the image only if not already present\n if (!context.pdfDocument.images[url]) {\n const dataUrl = await downloadImageAsDataUrl(url, context.fetchData);\n context.pdfDocument.images[url] = dataUrl;\n }\n\n // Extract all properties except 'smeup' from the image object\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { smeup, ...imageRest } = elementImage.image;\n\n return {\n ...elementImage,\n image: url,\n ...imageRest,\n };\n };\n};\n\nexport const objectToUrlAdapter = () => {\n return async (\n element: unknown,\n context: PdfMakeConverterContext,\n ): Promise<ElementWithImageExtension> => {\n if (!hasSmeupObject(element)) {\n return element as ElementWithImageExtension;\n }\n if (!context.getSmeupDataStructure || !context.damSvcEndpoint) {\n throw new Error(\n \"getSmeupDataStructure function and damSvcEndpoint prop are required in context when the smeup image obj property is used\",\n );\n } else {\n const elementImage = element as ElementWithImageExtension;\n const obj = elementImage.image.smeup?.obj;\n if (!obj || !obj.t || !obj.p || !obj.k) {\n throw new Error(\n \"Smeup object must have t, p, and k properties to build GET.PATH function\",\n );\n }\n const funToGetPATH = `F(TRE;JASER_12W;GET.PATH) 1(${obj.t};${obj.p};${obj.k})`;\n const dataTree = (await context.getSmeupDataStructure(\n funToGetPATH,\n )) as SmeupDataTree;\n if (dataTree.children?.length === 0) {\n throw new Error(`No data found for function ${funToGetPATH}`);\n } else {\n const pathNode = dataTree.children[0].value.replace(/\\\\/g, \"/\");\n const pathEncoded = encodeURIComponent(pathNode);\n const url = context.damSvcEndpoint + \"/\" + pathEncoded;\n\n // Extract all properties except 'smeup' from the image object\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { smeup, ...imageRest } = elementImage.image;\n\n return {\n ...elementImage,\n image: {\n smeup: {\n url,\n },\n ...imageRest,\n },\n };\n }\n }\n };\n};\n\nexport const imageAdapter = () => {\n return async (\n element: unknown,\n context: PdfMakeConverterContext,\n ): Promise<ContentImageExtension> => {\n try {\n const adaptedElement = await objectToUrlAdapter()(element, context);\n return await urlToImageAdapter()(adaptedElement, context);\n } catch (error) {\n console.error(error);\n const errorMessage = (error as Error).message;\n const cause = (error as Error & { cause?: Error }).cause;\n const causeMessage = cause ? `\\nCause: ${cause.message || cause}` : \"\";\n return {\n text: `Error loading image: ${errorMessage}${causeMessage}`,\n fontSize: 10,\n color: \"#8B0000\",\n } as unknown as ContentImageExtension;\n }\n };\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sme.up/doc-alchemist",
3
- "version": "1.5.0-SNAPSHOT-20251126090326",
3
+ "version": "1.5.0-SNAPSHOT-20251126145720",
4
4
  "description": "Library for generating documents in various formats, including Excel and PDF.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Smeup LAB <info@smeup.com> (https://www.smeup.com/)",