sheets
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -56,18 +56,9 @@ function normalizeExcelKey(value: string): string {
|
||||
.replace(/[^A-Z0-9]+/g, '');
|
||||
}
|
||||
|
||||
function extractDescriptionHtmlFromMdxBody(body: string): string {
|
||||
const content = String(body || '').trim();
|
||||
if (!content) return '';
|
||||
|
||||
// MDX product files are wrapped like:
|
||||
// <ProductTabs technicalData={...}>
|
||||
// <section>...</section>
|
||||
// </ProductTabs>
|
||||
// For PDF, we only want the inner description content.
|
||||
const withoutOpen = content.replace(/^\s*<ProductTabs[\s\S]*?>\s*/i, '');
|
||||
const withoutClose = withoutOpen.replace(/\s*<\/ProductTabs>\s*$/i, '');
|
||||
return withoutClose.trim();
|
||||
function extractDescriptionFromMdxFrontmatter(data: any): string {
|
||||
const description = normalizeValue(String(data?.description || ''));
|
||||
return description;
|
||||
}
|
||||
|
||||
function buildMdxIndex(locale: 'en' | 'de'): MdxIndex {
|
||||
@@ -93,7 +84,7 @@ function buildMdxIndex(locale: 'en' | 'de'): MdxIndex {
|
||||
const categories = Array.isArray(data.categories) ? data.categories.map((c: any) => normalizeValue(String(c))).filter(Boolean) : [];
|
||||
const images = Array.isArray(data.images) ? data.images.map((i: any) => normalizeValue(String(i))).filter(Boolean) : [];
|
||||
|
||||
const descriptionHtml = extractDescriptionHtmlFromMdxBody(parsed.content);
|
||||
const descriptionHtml = extractDescriptionFromMdxFrontmatter(data);
|
||||
|
||||
const slug = path.basename(file, '.mdx');
|
||||
idx.set(normalizeExcelKey(title), { slug, title, sku, categories, images, descriptionHtml });
|
||||
|
||||
@@ -639,10 +639,10 @@ function extractAbbrevColumnsFromMediumVoltageHeader(args: {
|
||||
function buildMediumVoltageCrossSectionTableFromNewExcel(args: {
|
||||
product: ProductData;
|
||||
locale: 'en' | 'de';
|
||||
}): BuildExcelModelResult {
|
||||
}): BuildExcelModelResult & { legendItems: KeyValueItem[] } {
|
||||
const mv = findMediumVoltageCrossSectionExcelForProduct(args.product) as MediumVoltageCrossSectionExcelMatch | null;
|
||||
if (!mv || !mv.rows.length) return { ok: false, technicalItems: [], voltageTables: [] };
|
||||
if (!mv.crossSectionKey) return { ok: false, technicalItems: [], voltageTables: [] };
|
||||
if (!mv || !mv.rows.length) return { ok: false, technicalItems: [], voltageTables: [], legendItems: [] };
|
||||
if (!mv.crossSectionKey) return { ok: false, technicalItems: [], voltageTables: [], legendItems: [] };
|
||||
|
||||
const abbrevCols = extractAbbrevColumnsFromMediumVoltageHeader({
|
||||
headerRow: mv.headerRow,
|
||||
@@ -651,7 +651,19 @@ function buildMediumVoltageCrossSectionTableFromNewExcel(args: {
|
||||
crossSectionKey: mv.crossSectionKey,
|
||||
ratedVoltageKey: mv.ratedVoltageKey,
|
||||
});
|
||||
if (!abbrevCols.length) return { ok: false, technicalItems: [], voltageTables: [] };
|
||||
if (!abbrevCols.length) return { ok: false, technicalItems: [], voltageTables: [], legendItems: [] };
|
||||
|
||||
// Collect legend items: abbreviation -> description from header row
|
||||
const legendItems: KeyValueItem[] = [];
|
||||
for (const col of abbrevCols) {
|
||||
const description = normalizeValue(String(mv.headerRow[col.colKey] || ''));
|
||||
if (description && description !== col.colKey) {
|
||||
legendItems.push({
|
||||
label: col.colKey,
|
||||
value: description,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const byVoltage = new Map<string, number[]>();
|
||||
for (let i = 0; i < mv.rows.length; i++) {
|
||||
@@ -710,7 +722,7 @@ function buildMediumVoltageCrossSectionTableFromNewExcel(args: {
|
||||
voltageTables.push({ voltageLabel: vKey, metaItems, crossSections, columns });
|
||||
}
|
||||
|
||||
return { ok: true, technicalItems: [], voltageTables };
|
||||
return { ok: true, technicalItems: [], voltageTables, legendItems };
|
||||
}
|
||||
|
||||
export function buildDatasheetModel(args: { product: ProductData; locale: 'en' | 'de' }): DatasheetModel {
|
||||
@@ -726,7 +738,7 @@ export function buildDatasheetModel(args: { product: ProductData; locale: 'en' |
|
||||
// Cross-section tables: for medium voltage only, prefer the new MV sheet (abbrev columns in header row).
|
||||
const crossSectionModel = isMediumVoltageProduct(args.product)
|
||||
? buildMediumVoltageCrossSectionTableFromNewExcel({ product: args.product, locale: args.locale })
|
||||
: { ok: false, technicalItems: [], voltageTables: [] };
|
||||
: { ok: false, technicalItems: [], voltageTables: [], legendItems: [] };
|
||||
|
||||
const voltageTablesSrc = crossSectionModel.ok
|
||||
? crossSectionModel.voltageTables
|
||||
@@ -762,5 +774,6 @@ export function buildDatasheetModel(args: { product: ProductData; locale: 'en' |
|
||||
labels,
|
||||
technicalItems: excelModel.ok ? excelModel.technicalItems : [],
|
||||
voltageTables,
|
||||
legendItems: crossSectionModel.legendItems || [],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -47,5 +47,6 @@ export type DatasheetModel = {
|
||||
};
|
||||
technicalItems: KeyValueItem[];
|
||||
voltageTables: DatasheetVoltageTable[];
|
||||
legendItems: KeyValueItem[];
|
||||
};
|
||||
|
||||
|
||||
@@ -62,12 +62,18 @@ export function DatasheetDocument(props: { model: DatasheetModel; assets: Assets
|
||||
<Footer locale={model.locale} siteUrl={CONFIG.siteUrl} />
|
||||
|
||||
{model.voltageTables.map((t: DatasheetVoltageTable) => (
|
||||
<View key={t.voltageLabel} style={{ marginBottom: 14 }}>
|
||||
<View key={t.voltageLabel} style={{ marginBottom: 14 }} break={false}>
|
||||
<Text style={styles.sectionTitle}>{`${model.labels.crossSection} — ${t.voltageLabel}`}</Text>
|
||||
|
||||
<DenseTable table={{ columns: t.columns, rows: t.rows }} firstColLabel={firstColLabel} />
|
||||
</View>
|
||||
))}
|
||||
|
||||
{model.legendItems.length ? (
|
||||
<Section title={model.locale === 'de' ? 'ABKÜRZUNGEN' : 'ABBREVIATIONS'}>
|
||||
<KeyValueGrid items={model.legendItems} />
|
||||
</Section>
|
||||
) : null}
|
||||
</Page>
|
||||
</Document>
|
||||
);
|
||||
|
||||
@@ -27,16 +27,19 @@ async function readBytesFromPublic(localPath: string): Promise<Uint8Array> {
|
||||
|
||||
function transformLogoSvgToPrintBlack(svg: string): string {
|
||||
return svg
|
||||
.replace(/fill\s*:\s*white/gi, 'fill:#0E2A47')
|
||||
.replace(/fill\s*=\s*"white"/gi, 'fill="#0E2A47"')
|
||||
.replace(/fill\s*=\s*'white'/gi, "fill='#0E2A47'");
|
||||
.replace(/fill\s*:\s*white/gi, 'fill:#000000')
|
||||
.replace(/fill\s*=\s*"white"/gi, 'fill="#000000"')
|
||||
.replace(/fill\s*=\s*'white'/gi, "fill='#000000'")
|
||||
.replace(/fill\s*:\s*#[0-9a-fA-F]{6}/gi, 'fill:#000000')
|
||||
.replace(/fill\s*=\s*"#[0-9a-fA-F]{6}"/gi, 'fill="#000000"')
|
||||
.replace(/fill\s*=\s*'#[0-9a-fA-F]{6}'/gi, "fill='#000000'");
|
||||
}
|
||||
|
||||
async function toPngBytes(inputBytes: Uint8Array, inputHint: string): Promise<Uint8Array> {
|
||||
const ext = (path.extname(inputHint).toLowerCase() || '').replace('.', '');
|
||||
if (ext === 'png') return inputBytes;
|
||||
|
||||
if (ext === 'svg' && /\/media\/logo\.svg$/i.test(inputHint)) {
|
||||
if (ext === 'svg' && (/\/media\/logo\.svg$/i.test(inputHint) || /\/logo-blue\.svg$/i.test(inputHint))) {
|
||||
const svg = Buffer.from(inputBytes).toString('utf8');
|
||||
inputBytes = new Uint8Array(Buffer.from(transformLogoSvgToPrintBlack(svg), 'utf8'));
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ export function DenseTable(props: {
|
||||
const headerFontSize = cols.length >= 14 ? 5.7 : cols.length >= 12 ? 5.9 : cols.length >= 10 ? 6.2 : 6.6;
|
||||
|
||||
return (
|
||||
<View style={styles.tableWrap}>
|
||||
<View style={styles.tableWrap} break={false}>
|
||||
<View style={styles.tableHeader} wrap={false}>
|
||||
<View style={{ width: cfgW }}>
|
||||
<Text
|
||||
|
||||
@@ -13,8 +13,8 @@ export async function generateDatasheetPdfBuffer(args: {
|
||||
const model = buildDatasheetModel({ product: args.product, locale: args.locale });
|
||||
|
||||
const logoDataUrl =
|
||||
(await loadImageAsPngDataUrl('/media/logo.svg')) ||
|
||||
(await loadImageAsPngDataUrl('/media/logo.webp')) ||
|
||||
(await loadImageAsPngDataUrl('/logo-blue.svg')) ||
|
||||
(await loadImageAsPngDataUrl('/logo-white.svg')) ||
|
||||
null;
|
||||
|
||||
const heroDataUrl = await loadImageAsPngDataUrl(model.product.heroSrc);
|
||||
|
||||
Reference in New Issue
Block a user