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