fix(nextjs): makes box with shadow inherit color from parents to fix export issue
This commit is contained in:
parent
c760736e51
commit
039048f139
6 changed files with 146 additions and 164 deletions
|
|
@ -54,9 +54,9 @@ class PptxPositionModel(BaseModel):
|
|||
class PptxFontModel(BaseModel):
|
||||
name: str = "Inter"
|
||||
size: int = 16
|
||||
bold: bool = False
|
||||
italic: bool = False
|
||||
color: str = "000000"
|
||||
font_weight: Optional[int] = 400
|
||||
|
||||
|
||||
class PptxFillModel(BaseModel):
|
||||
|
|
|
|||
|
|
@ -57,23 +57,47 @@ class PptxPresentationCreator:
|
|||
|
||||
async def fetch_network_assets(self):
|
||||
image_urls = []
|
||||
models_with_network_asset: List[PptxPictureBoxModel] = []
|
||||
|
||||
if self._ppt_model.shapes:
|
||||
for each_shape in self._ppt_model.shapes:
|
||||
if isinstance(each_shape, PptxPictureBoxModel):
|
||||
image_path = each_shape.picture.path
|
||||
if image_path.startswith("http"):
|
||||
if "app_data/images" in image_path:
|
||||
relative_path = image_path.split("/app_data/images/")[1]
|
||||
each_shape.picture.path = os.path.join(
|
||||
"app_data/images", relative_path
|
||||
)
|
||||
each_shape.picture.is_network = False
|
||||
continue
|
||||
image_urls.append(image_path)
|
||||
models_with_network_asset.append(each_shape)
|
||||
|
||||
for each_slide in self._slide_models:
|
||||
models_with_network_asset: List[PptxPictureBoxModel] = []
|
||||
for each_shape in each_slide.shapes:
|
||||
if isinstance(each_shape, PptxPictureBoxModel):
|
||||
image_path = each_shape.picture.path
|
||||
if not image_path.startswith("http"):
|
||||
continue
|
||||
image_urls.append(image_path)
|
||||
models_with_network_asset.append(each_shape)
|
||||
if image_path.startswith("http"):
|
||||
if "app_data/images" in image_path:
|
||||
relative_path = image_path.split("/app_data/images/")[1]
|
||||
each_shape.picture.path = os.path.join(
|
||||
"app_data/images", relative_path
|
||||
)
|
||||
each_shape.picture.is_network = False
|
||||
continue
|
||||
image_urls.append(image_path)
|
||||
models_with_network_asset.append(each_shape)
|
||||
|
||||
if image_urls:
|
||||
image_paths = await download_files(image_urls, self._temp_dir)
|
||||
|
||||
for each_shape, each_image_path in zip(
|
||||
models_with_network_asset, image_paths
|
||||
):
|
||||
each_shape.picture.path = each_image_path
|
||||
each_shape.picture.is_network = False
|
||||
if each_image_path:
|
||||
each_shape.picture.path = each_image_path
|
||||
each_shape.picture.is_network = False
|
||||
|
||||
async def create_ppt(self):
|
||||
await self.fetch_network_assets()
|
||||
|
|
@ -261,6 +285,7 @@ class PptxPresentationCreator:
|
|||
font_json = font.model_dump()
|
||||
font_json["bold"] = True
|
||||
font_json["italic"] = True
|
||||
font_json["font_weight"] = 700 # Set font weight to bold
|
||||
text_runs.append(
|
||||
PptxTextRunModel(
|
||||
text=text_content, font=PptxFontModel(**font_json)
|
||||
|
|
@ -276,6 +301,7 @@ class PptxPresentationCreator:
|
|||
text_content = line[current_pos + 2 : end_pos]
|
||||
font_json = font.model_dump()
|
||||
font_json["bold"] = True
|
||||
font_json["font_weight"] = 700 # Set font weight to bold
|
||||
text_runs.append(
|
||||
PptxTextRunModel(
|
||||
text=text_content, font=PptxFontModel(**font_json)
|
||||
|
|
@ -434,9 +460,9 @@ class PptxPresentationCreator:
|
|||
def apply_font(self, font: Font, font_model: PptxFontModel):
|
||||
font.name = font_model.name
|
||||
font.color.rgb = RGBColor.from_string(font_model.color)
|
||||
font.bold = font_model.bold
|
||||
font.italic = font_model.italic
|
||||
font.size = Pt(font_model.size)
|
||||
font.bold = font_model.font_weight >= 600
|
||||
|
||||
def save(self, path: str):
|
||||
self._ppt.save(path)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,15 @@ import { ElementAttributes, SlideAttributesResult } from "@/types/element_attibu
|
|||
import { convertElementAttributesToPptxSlides } from "@/utils/pptx_models_utils";
|
||||
import { PptxPresentationModel } from "@/types/pptx_models";
|
||||
|
||||
// Interface for getAllChildElementsAttributes function arguments
|
||||
interface GetAllChildElementsAttributesArgs {
|
||||
element: ElementHandle<Element>;
|
||||
rootRect?: { left: number; top: number; width: number; height: number } | null;
|
||||
depth?: number;
|
||||
inheritedFont?: ElementAttributes['font'];
|
||||
inheritedBackground?: ElementAttributes['background'];
|
||||
}
|
||||
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
let browser: Browser | null = null;
|
||||
|
|
@ -49,7 +58,7 @@ async function getPresentationId(request: NextRequest) {
|
|||
|
||||
async function getSlidesAttributes(slides: ElementHandle<Element>[]) {
|
||||
const slideResults = await Promise.all(slides.map(async (slide) => {
|
||||
return await getAllChildElementsAttributes(slide);
|
||||
return await getAllChildElementsAttributes({ element: slide });
|
||||
}));
|
||||
|
||||
const elements = slideResults.map(result => result.elements);
|
||||
|
|
@ -84,7 +93,6 @@ async function getPresentationPage(browser: Browser, id: string) {
|
|||
page.on('console', (msg) => {
|
||||
const type = msg.type();
|
||||
const text = msg.text();
|
||||
console.log(`[Puppeteer Console ${type.toUpperCase()}] ${text}`);
|
||||
});
|
||||
|
||||
await page.setViewport({ width: 1640, height: 720, deviceScaleFactor: 1 });
|
||||
|
|
@ -96,8 +104,9 @@ async function getPresentationPage(browser: Browser, id: string) {
|
|||
}
|
||||
|
||||
|
||||
async function getAllChildElementsAttributes(element: ElementHandle<Element>): Promise<SlideAttributesResult> {
|
||||
const rootRect = await element.evaluate((el) => {
|
||||
async function getAllChildElementsAttributes({ element, rootRect = null, depth = 0, inheritedFont, inheritedBackground }: GetAllChildElementsAttributesArgs): Promise<SlideAttributesResult> {
|
||||
// Get rootRect if not provided (first call)
|
||||
const currentRootRect = rootRect || await element.evaluate((el) => {
|
||||
const rect = el.getBoundingClientRect();
|
||||
return {
|
||||
left: isFinite(rect.left) ? rect.left : 0,
|
||||
|
|
@ -107,54 +116,71 @@ async function getAllChildElementsAttributes(element: ElementHandle<Element>): P
|
|||
};
|
||||
});
|
||||
|
||||
const childElementHandles = await element.$$(':scope *');
|
||||
// Get direct children only (not all descendants)
|
||||
const directChildElementHandles = await element.$$(':scope > *');
|
||||
|
||||
const attributesPromises = childElementHandles.map(async (childElementHandle) => {
|
||||
const allResults: { attributes: ElementAttributes; depth: number }[] = [];
|
||||
|
||||
// Process direct children recursively
|
||||
for (const childElementHandle of directChildElementHandles) {
|
||||
// Get attributes for current child
|
||||
const attributes = await getElementAttributes(childElementHandle);
|
||||
|
||||
const depth = await childElementHandle.evaluate((el) => {
|
||||
let depth = 0;
|
||||
let current = el;
|
||||
while (current.parentElement) {
|
||||
depth++;
|
||||
current = current.parentElement;
|
||||
}
|
||||
return depth;
|
||||
});
|
||||
// Apply inherited font only on elements that have direct text
|
||||
if (inheritedFont && !attributes.font && attributes.innerText && attributes.innerText.trim().length > 0) {
|
||||
attributes.font = inheritedFont;
|
||||
}
|
||||
// Apply inherited background only on elements that have shadow
|
||||
if (inheritedBackground && !attributes.background && attributes.shadow) {
|
||||
attributes.background = inheritedBackground;
|
||||
}
|
||||
|
||||
// Adjust position relative to root
|
||||
if (attributes.position && attributes.position.left !== undefined && attributes.position.top !== undefined) {
|
||||
attributes.position = {
|
||||
left: attributes.position.left - rootRect.left,
|
||||
top: attributes.position.top - rootRect.top,
|
||||
left: attributes.position.left - currentRootRect.left,
|
||||
top: attributes.position.top - currentRootRect.top,
|
||||
width: attributes.position.width,
|
||||
height: attributes.position.height,
|
||||
};
|
||||
}
|
||||
|
||||
return { attributes, depth };
|
||||
});
|
||||
// Add current child to results
|
||||
allResults.push({ attributes, depth });
|
||||
|
||||
const allResults = await Promise.all(attributesPromises);
|
||||
// Recursively process children of this child
|
||||
const childResults = await getAllChildElementsAttributes({
|
||||
element: childElementHandle,
|
||||
rootRect: currentRootRect,
|
||||
depth: depth + 1,
|
||||
inheritedFont: attributes.font || inheritedFont,
|
||||
inheritedBackground: attributes.background || inheritedBackground,
|
||||
});
|
||||
allResults.push(...childResults.elements.map(attr => ({ attributes: attr, depth: depth + 1 })));
|
||||
}
|
||||
|
||||
// Find background color from elements with root position (only in first call)
|
||||
let backgroundColor: string | undefined;
|
||||
const elementsWithRootPosition = allResults.filter(({ attributes }) => {
|
||||
return attributes.position &&
|
||||
attributes.position.left === 0 &&
|
||||
attributes.position.top === 0 &&
|
||||
attributes.position.width === rootRect.width &&
|
||||
attributes.position.height === rootRect.height;
|
||||
});
|
||||
if (!rootRect) {
|
||||
const elementsWithRootPosition = allResults.filter(({ attributes }) => {
|
||||
return attributes.position &&
|
||||
attributes.position.left === 0 &&
|
||||
attributes.position.top === 0 &&
|
||||
attributes.position.width === currentRootRect.width &&
|
||||
attributes.position.height === currentRootRect.height;
|
||||
});
|
||||
|
||||
for (const { attributes } of elementsWithRootPosition) {
|
||||
if (attributes.background && attributes.background.color) {
|
||||
backgroundColor = attributes.background.color;
|
||||
break;
|
||||
for (const { attributes } of elementsWithRootPosition) {
|
||||
if (attributes.background && attributes.background.color) {
|
||||
backgroundColor = attributes.background.color;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const filteredResults = allResults.filter(({ attributes }) => {
|
||||
const hasOwnBackground = attributes.background && attributes.background.color && !attributes.background.isInherited;
|
||||
const hasInheritedBackground = attributes.background && attributes.background.color && attributes.background.isInherited;
|
||||
// Filter results (only in first call)
|
||||
const filteredResults = !rootRect ? allResults.filter(({ attributes }) => {
|
||||
const hasBackground = attributes.background && attributes.background.color;
|
||||
const hasBorder = attributes.border && attributes.border.color;
|
||||
const hasShadow = attributes.shadow && attributes.shadow.color;
|
||||
const hasText = attributes.innerText && attributes.innerText.trim().length > 0;
|
||||
|
|
@ -163,40 +189,54 @@ async function getAllChildElementsAttributes(element: ElementHandle<Element>): P
|
|||
const isRootPosition = attributes.position &&
|
||||
attributes.position.left === 0 &&
|
||||
attributes.position.top === 0 &&
|
||||
attributes.position.width === rootRect.width &&
|
||||
attributes.position.height === rootRect.height;
|
||||
attributes.position.width === currentRootRect.width &&
|
||||
attributes.position.height === currentRootRect.height;
|
||||
|
||||
// Include elements that have meaningful visual properties
|
||||
// Elements with own background colors, borders, shadows, text, or images should be included
|
||||
// Elements with only inherited background colors should only be included if they have other properties
|
||||
const hasOtherProperties = hasBorder || hasShadow || hasText || hasImage;
|
||||
const hasVisualProperties = hasOwnBackground || hasOtherProperties || (hasInheritedBackground && hasOtherProperties);
|
||||
const hasOtherProperties = hasBackground || hasBorder || hasShadow || hasText || hasImage;
|
||||
return hasOtherProperties && !isRootPosition;
|
||||
}) : allResults;
|
||||
|
||||
return hasVisualProperties && !isRootPosition;
|
||||
});
|
||||
if (!rootRect) {
|
||||
const sortedElements = filteredResults
|
||||
.sort((a, b) => {
|
||||
const zIndexA = a.attributes.zIndex || 0;
|
||||
const zIndexB = b.attributes.zIndex || 0;
|
||||
|
||||
const sortedElements = filteredResults
|
||||
.sort((a, b) => {
|
||||
const zIndexA = a.attributes.zIndex || 0;
|
||||
const zIndexB = b.attributes.zIndex || 0;
|
||||
if (zIndexA === zIndexB) {
|
||||
return b.depth - a.depth;
|
||||
}
|
||||
|
||||
if (zIndexA === zIndexB) {
|
||||
return b.depth - a.depth;
|
||||
}
|
||||
return zIndexB - zIndexA;
|
||||
})
|
||||
.map(({ attributes }) => {
|
||||
// Set background color to backgroundColor for elements that have shadow but no background color
|
||||
if (attributes.shadow && attributes.shadow.color && (!attributes.background || !attributes.background.color) && backgroundColor) {
|
||||
attributes.background = {
|
||||
color: backgroundColor,
|
||||
opacity: undefined
|
||||
};
|
||||
}
|
||||
return attributes;
|
||||
});
|
||||
|
||||
return zIndexB - zIndexA;
|
||||
})
|
||||
.map(({ attributes }) => attributes);
|
||||
|
||||
return {
|
||||
elements: sortedElements,
|
||||
backgroundColor
|
||||
};
|
||||
return {
|
||||
elements: sortedElements,
|
||||
backgroundColor
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
elements: filteredResults.map(({ attributes }) => attributes),
|
||||
backgroundColor
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Do not edit this function, it is used to get the attributes of an element
|
||||
async function getElementAttributes(element: ElementHandle<Element>): Promise<ElementAttributes> {
|
||||
const attributes = await element.evaluate((el) => {
|
||||
|
||||
const attributes = await element.evaluate((el: Element) => {
|
||||
|
||||
function colorToHex(color: string): { hex: string | undefined; opacity: number | undefined } {
|
||||
if (!color || color === 'transparent' || color === 'rgba(0, 0, 0, 0)') {
|
||||
return { hex: undefined, opacity: undefined };
|
||||
|
|
@ -278,45 +318,12 @@ async function getElementAttributes(element: ElementHandle<Element>): Promise<El
|
|||
|
||||
|
||||
|
||||
function getInheritedBackgroundColor(el: Element): { color: string | undefined; opacity: number | undefined } {
|
||||
let current = el.parentElement;
|
||||
while (current) {
|
||||
const computedStyles = window.getComputedStyle(current);
|
||||
const backgroundColorResult = colorToHex(computedStyles.backgroundColor);
|
||||
// Only return inherited background if it's not transparent and has a meaningful color
|
||||
// (not black or white, which are likely defaults)
|
||||
if (backgroundColorResult.hex && backgroundColorResult.opacity !== 0 &&
|
||||
backgroundColorResult.hex !== '000000' && backgroundColorResult.hex !== 'ffffff' &&
|
||||
backgroundColorResult.hex !== 'transparent') {
|
||||
return {
|
||||
color: backgroundColorResult.hex,
|
||||
opacity: backgroundColorResult.opacity,
|
||||
};
|
||||
}
|
||||
current = current.parentElement;
|
||||
}
|
||||
return { color: undefined, opacity: undefined };
|
||||
}
|
||||
|
||||
function parseBackground(computedStyles: CSSStyleDeclaration, el?: Element, hasShadow?: boolean) {
|
||||
function parseBackground(computedStyles: CSSStyleDeclaration) {
|
||||
const backgroundColorResult = colorToHex(computedStyles.backgroundColor);
|
||||
|
||||
// Only use inherited background if the element has no background color at all
|
||||
// and has a shadow (indicating it might need a background for the shadow to be visible)
|
||||
if (!backgroundColorResult.hex && hasShadow && el) {
|
||||
const inheritedBackground = getInheritedBackgroundColor(el);
|
||||
if (inheritedBackground.color) {
|
||||
return {
|
||||
...inheritedBackground,
|
||||
isInherited: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
color: backgroundColorResult.hex,
|
||||
opacity: backgroundColorResult.opacity,
|
||||
isInherited: false
|
||||
opacity: backgroundColorResult.opacity
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -332,7 +339,6 @@ async function getElementAttributes(element: ElementHandle<Element>): Promise<El
|
|||
function parseShadow(computedStyles: CSSStyleDeclaration) {
|
||||
const boxShadow = computedStyles.boxShadow;
|
||||
if (boxShadow !== 'none') {
|
||||
console.log(`Parsing shadow: ${boxShadow}`);
|
||||
}
|
||||
let shadow: {
|
||||
offset?: [number, number];
|
||||
|
|
@ -371,7 +377,7 @@ async function getElementAttributes(element: ElementHandle<Element>): Promise<El
|
|||
shadows.push(currentShadow.trim());
|
||||
}
|
||||
|
||||
console.log(`Split shadows: ${JSON.stringify(shadows)}`);
|
||||
|
||||
|
||||
let selectedShadow = '';
|
||||
let bestShadowScore = -1;
|
||||
|
|
@ -431,22 +437,17 @@ async function getElementAttributes(element: ElementHandle<Element>): Promise<El
|
|||
}
|
||||
}
|
||||
|
||||
console.log(`Shadow ${i} - numericParts: ${JSON.stringify(numericParts)}, colorParts: ${JSON.stringify(colorParts)}`);
|
||||
|
||||
// Check if the color is not completely transparent using colorToHex
|
||||
let hasVisibleColor = false;
|
||||
if (colorParts.length > 0) {
|
||||
const shadowColor = colorParts.join(' ');
|
||||
const colorResult = colorToHex(shadowColor);
|
||||
hasVisibleColor = !!(colorResult.hex && colorResult.hex !== '000000' && colorResult.opacity !== 0);
|
||||
console.log(`Shadow ${i} color analysis - color: "${shadowColor}", result: ${JSON.stringify(colorResult)}, hasVisibleColor: ${hasVisibleColor}`);
|
||||
}
|
||||
|
||||
// Check if we have any non-zero numeric values (offset, blur, or spread)
|
||||
const hasNonZeroValues = numericParts.some(value => value !== 0);
|
||||
|
||||
console.log(`Shadow ${i} - hasNonZeroValues: ${hasNonZeroValues}, hasVisibleColor: ${hasVisibleColor}`);
|
||||
|
||||
// Calculate a score for this shadow (higher is better)
|
||||
let shadowScore = 0;
|
||||
if (hasNonZeroValues) {
|
||||
|
|
@ -461,18 +462,15 @@ async function getElementAttributes(element: ElementHandle<Element>): Promise<El
|
|||
if ((hasNonZeroValues || hasVisibleColor) && shadowScore > bestShadowScore) {
|
||||
selectedShadow = shadowStr;
|
||||
bestShadowScore = shadowScore;
|
||||
console.log(`Selected shadow ${i} with score ${shadowScore}: "${selectedShadow}"`);
|
||||
}
|
||||
}
|
||||
|
||||
// If no meaningful shadow found, use the first one
|
||||
if (!selectedShadow && shadows.length > 0) {
|
||||
selectedShadow = shadows[0];
|
||||
console.log(`No meaningful shadow found, using first: "${selectedShadow}"`);
|
||||
}
|
||||
|
||||
if (selectedShadow) {
|
||||
console.log(`Parsing selected shadow: "${selectedShadow}"`);
|
||||
|
||||
// Parse the selected shadow
|
||||
const shadowParts = selectedShadow.split(' ');
|
||||
|
|
@ -525,8 +523,6 @@ async function getElementAttributes(element: ElementHandle<Element>): Promise<El
|
|||
}
|
||||
}
|
||||
|
||||
console.log(`Selected shadow parsing - numericParts: ${JSON.stringify(numericParts)}, colorParts: ${JSON.stringify(colorParts)}`);
|
||||
|
||||
// Handle different shadow formats
|
||||
if (numericParts.length >= 2) {
|
||||
const offsetX = numericParts[0];
|
||||
|
|
@ -541,14 +537,11 @@ async function getElementAttributes(element: ElementHandle<Element>): Promise<El
|
|||
}
|
||||
|
||||
const shadowColorResult = colorToHex(shadowColor);
|
||||
console.log(`Shadow color result: ${JSON.stringify(shadowColorResult)}`);
|
||||
|
||||
// Create shadow object if we have any meaningful values or visible color
|
||||
const hasValidValues = offsetX !== 0 || offsetY !== 0 || blurRadius > 0 || spreadRadius !== 0 ||
|
||||
(shadowColorResult.hex && shadowColorResult.hex !== '000000' && shadowColorResult.opacity !== 0);
|
||||
|
||||
console.log(`Has valid values: ${hasValidValues} (offsetX: ${offsetX}, offsetY: ${offsetY}, blurRadius: ${blurRadius}, spreadRadius: ${spreadRadius}, color: ${shadowColorResult.hex}, opacity: ${shadowColorResult.opacity})`);
|
||||
|
||||
if (hasValidValues) {
|
||||
shadow = {
|
||||
offset: [offsetX, offsetY],
|
||||
|
|
@ -559,16 +552,11 @@ async function getElementAttributes(element: ElementHandle<Element>): Promise<El
|
|||
inset: isInset,
|
||||
angle: Math.atan2(offsetY, offsetX) * (180 / Math.PI),
|
||||
};
|
||||
console.log(`Created shadow object: ${JSON.stringify(shadow)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (boxShadow !== 'none') {
|
||||
console.log(`Final parsed shadow: ${JSON.stringify(shadow)}`);
|
||||
}
|
||||
|
||||
return shadow;
|
||||
}
|
||||
|
||||
|
|
@ -663,7 +651,7 @@ async function getElementAttributes(element: ElementHandle<Element>): Promise<El
|
|||
|
||||
const shadow = parseShadow(computedStyles);
|
||||
|
||||
const background = parseBackground(computedStyles, el, !!shadow);
|
||||
const background = parseBackground(computedStyles);
|
||||
|
||||
const border = parseBorder(computedStyles);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ export interface ElementAttributes {
|
|||
background?: {
|
||||
color?: string;
|
||||
opacity?: number;
|
||||
isInherited?: boolean;
|
||||
};
|
||||
border?: {
|
||||
color?: string;
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ export interface PptxPositionModel {
|
|||
export interface PptxFontModel {
|
||||
name: string;
|
||||
size: number;
|
||||
bold: boolean;
|
||||
font_weight: number;
|
||||
italic: boolean;
|
||||
color: string;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import {
|
|||
PptxPictureBoxModel,
|
||||
PptxConnectorModel,
|
||||
PptxPositionModel,
|
||||
PptxSpacingModel,
|
||||
PptxFillModel,
|
||||
PptxStrokeModel,
|
||||
PptxShadowModel,
|
||||
|
|
@ -110,23 +109,12 @@ function convertToTextBox(element: ElementAttributes): PptxTextBoxModel {
|
|||
height: Math.round(element.position?.height ?? 0)
|
||||
};
|
||||
|
||||
const margin: PptxSpacingModel | undefined = element.margin ? {
|
||||
top: Math.round(element.margin.top ?? 0),
|
||||
bottom: Math.round(element.margin.bottom ?? 0),
|
||||
left: Math.round(element.margin.left ?? 0),
|
||||
right: Math.round(element.margin.right ?? 0)
|
||||
} : undefined;
|
||||
|
||||
const fill: PptxFillModel | undefined = element.background?.color ?
|
||||
(element.background.isInherited ?
|
||||
(element.shadow?.color ? { color: element.background.color } : undefined) :
|
||||
{ color: element.background.color }
|
||||
) : undefined;
|
||||
const fill: PptxFillModel | undefined = element.background?.color ? { color: element.background.color } : undefined;
|
||||
|
||||
const font: PptxFontModel | undefined = element.font ? {
|
||||
name: element.font.name ?? "Inter",
|
||||
size: Math.round(element.font.size ?? 16),
|
||||
bold: element.font.weight ? element.font.weight >= 600 : false,
|
||||
font_weight: element.font.weight ?? 400,
|
||||
italic: element.font.italic ?? false,
|
||||
color: element.font.color ?? "000000"
|
||||
} : undefined;
|
||||
|
|
@ -139,7 +127,7 @@ function convertToTextBox(element: ElementAttributes): PptxTextBoxModel {
|
|||
};
|
||||
|
||||
return {
|
||||
margin,
|
||||
margin: undefined,
|
||||
fill,
|
||||
position,
|
||||
text_wrap: element.textWrap ?? true,
|
||||
|
|
@ -157,19 +145,7 @@ function convertToAutoShapeBox(element: ElementAttributes): PptxAutoShapeBoxMode
|
|||
width: Math.round(element.position?.width ?? 0),
|
||||
height: Math.round(element.position?.height ?? 0)
|
||||
};
|
||||
|
||||
const margin: PptxSpacingModel | undefined = element.margin ? {
|
||||
top: Math.round(element.margin.top ?? 0),
|
||||
bottom: Math.round(element.margin.bottom ?? 0),
|
||||
left: Math.round(element.margin.left ?? 0),
|
||||
right: Math.round(element.margin.right ?? 0)
|
||||
} : undefined;
|
||||
|
||||
const fill: PptxFillModel | undefined = element.background?.color ?
|
||||
(element.background.isInherited ?
|
||||
(element.shadow?.color ? { color: element.background.color } : undefined) :
|
||||
{ color: element.background.color }
|
||||
) : undefined;
|
||||
const fill: PptxFillModel | undefined = element.background?.color ? { color: element.background.color } : undefined;
|
||||
|
||||
const stroke: PptxStrokeModel | undefined = element.border?.color ? {
|
||||
color: element.border.color,
|
||||
|
|
@ -191,7 +167,7 @@ function convertToAutoShapeBox(element: ElementAttributes): PptxAutoShapeBoxMode
|
|||
font: element.font ? {
|
||||
name: element.font.name ?? "Inter",
|
||||
size: Math.round(element.font.size ?? 16), // int
|
||||
bold: element.font.weight ? element.font.weight >= 600 : false,
|
||||
font_weight: element.font.weight ?? 400,
|
||||
italic: element.font.italic ?? false,
|
||||
color: element.font.color ?? "000000"
|
||||
} : undefined,
|
||||
|
|
@ -200,7 +176,7 @@ function convertToAutoShapeBox(element: ElementAttributes): PptxAutoShapeBoxMode
|
|||
|
||||
return {
|
||||
type: PptxShapeType.ROUNDED_RECTANGLE, // Default to rounded rectangle
|
||||
margin,
|
||||
margin: undefined,
|
||||
fill,
|
||||
stroke,
|
||||
shadow,
|
||||
|
|
@ -222,13 +198,6 @@ function convertToPictureBox(element: ElementAttributes): PptxPictureBoxModel {
|
|||
height: Math.round(element.position?.height ?? 0)
|
||||
};
|
||||
|
||||
const margin: PptxSpacingModel | undefined = element.margin ? {
|
||||
top: Math.round(element.margin.top ?? 0),
|
||||
bottom: Math.round(element.margin.bottom ?? 0),
|
||||
left: Math.round(element.margin.left ?? 0),
|
||||
right: Math.round(element.margin.right ?? 0)
|
||||
} : undefined;
|
||||
|
||||
const objectFit: PptxObjectFitModel = {
|
||||
fit: element.objectFit ? (element.objectFit as PptxObjectFitEnum) : PptxObjectFitEnum.CONTAIN
|
||||
};
|
||||
|
|
@ -241,7 +210,7 @@ function convertToPictureBox(element: ElementAttributes): PptxPictureBoxModel {
|
|||
|
||||
return {
|
||||
position,
|
||||
margin,
|
||||
margin: undefined,
|
||||
clip: element.clip ?? true,
|
||||
overlay: element.overlay,
|
||||
border_radius: element.borderRadius ? element.borderRadius.map(r => Math.round(r)) : undefined, // List[int] - 4 elements from route parsing
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue