kdp-book-generator
Version:
Generate KDP-compliant PDFs and EPUBs from Markdown for Amazon book publishing
380 lines • 11.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.BookConfigManager = void 0;
/**
* Manager for book configuration with KDP-compliant defaults and validation
*
* Features:
* - Pre-defined KDP-compliant book formats
* - Automatic margin calculation based on page count
* - Configuration validation and merging
* - Typography presets for professional book layout
*/
class BookConfigManager {
/**
* Get the default book configuration with KDP-compliant settings
*
* @returns Default BookConfig with 6"x9" format and standard typography
*/
static getDefaultConfig() {
return {
title: 'My Book',
author: 'Author Name',
format: this.KDP_FORMATS['6x9'],
margins: this.calculateKDPMargins(200, '6x9'), // Default for 200 pages
typography: this.getDefaultTypography(),
pageNumbers: this.getDefaultPageNumbers(),
tableOfContents: true,
bleed: false,
};
}
static getKindleConfig() {
return {
title: 'My Book',
author: 'Author Name',
format: this.KDP_FORMATS['kindle'],
margins: this.getKindleMargins(),
typography: this.getKindleTypography(),
pageNumbers: this.getKindlePageNumbers(),
tableOfContents: true,
bleed: false,
};
}
/**
* Calculate KDP-compliant margins based on page count
*
* @param pageCount - Total number of pages in the book
* @param format - Book format identifier (e.g., '6x9', '5.5x8.5')
* @returns Margins object with calculated inside/outside margins per KDP requirements
*
* KDP margin requirements:
* - 24 pages or less: 0.375" inside
* - 25-150 pages: 0.5" inside
* - 151-300 pages: 0.625" inside
* - 301-500 pages: 0.75" inside
* - 501+ pages: 0.875" inside
*/
static calculateKDPMargins(pageCount, format) {
const formatData = this.KDP_FORMATS[format];
if (!formatData) {
throw new Error(`Unknown format: ${format}`);
}
// Fixed margins as requested
const insideMargin = 0.625;
const outsideMargin = 0.625;
// Default margins for top and bottom
const topMargin = 0.625;
const bottomMargin = 0.625;
return {
top: topMargin,
bottom: bottomMargin,
inside: insideMargin,
outside: outsideMargin,
unit: 'in',
};
}
static getDefaultTypography() {
const bodyFont = {
family: 'Nunito',
size: 11,
lineHeight: 1.5,
weight: 'normal',
style: 'normal',
color: '#000000',
marginTop: 0,
marginBottom: 10,
};
return {
body: bodyFont,
heading1: {
family: 'Lexend',
size: 20,
lineHeight: 1.3,
weight: 'normal',
style: 'normal',
color: '#000000',
marginTop: 48,
marginBottom: 24,
},
heading2: {
family: 'Lexend',
size: 17,
lineHeight: 1.3,
weight: 'bold',
style: 'normal',
color: '#000000',
marginTop: 42,
marginBottom: 18,
},
heading3: {
family: 'Lexend',
size: 13,
lineHeight: 1.3,
weight: 'bold',
style: 'normal',
color: '#000000',
marginTop: 36,
marginBottom: 16,
},
heading4: {
family: 'Lexend',
size: 11,
lineHeight: 1.3,
weight: 'bold',
style: 'normal',
color: '#000000',
marginTop: 24,
marginBottom: 12,
},
heading5: {
family: 'Lexend',
size: 10,
lineHeight: 1.3,
weight: 'bold',
style: 'normal',
color: '#000000',
marginTop: 20,
marginBottom: 10,
},
heading6: {
family: 'Lexend',
size: 9,
lineHeight: 1.3,
weight: 'bold',
style: 'normal',
color: '#000000',
marginTop: 18,
marginBottom: 8,
},
};
}
static getDefaultPageNumbers() {
return {
enabled: true,
startPage: 1,
format: 'decimal',
position: 'footer',
alignment: 'center',
};
}
static validateConfig(config) {
const errors = [];
// Validate format
if (!config.format || !config.format.width || !config.format.height) {
errors.push('Invalid format configuration');
}
// Check if this is Kindle format
const isKindle = config.format && config.format.name === 'Kindle';
// Validate margins
if (!config.margins) {
errors.push('Margins configuration is required');
}
else {
const { top, bottom, inside, outside } = config.margins;
if (isKindle) {
// Kindle has different margin requirements
if (top < 0.25 || bottom < 0.25 || inside < 0.25 || outside < 0.25) {
errors.push('Kindle margins must be at least 0.25"');
}
}
else {
// Standard KDP print requirements
if (top < 0.25 || bottom < 0.25 || inside < 0.375 || outside < 0.25) {
errors.push('Margins do not meet KDP minimum requirements');
}
}
}
// Validate typography
if (!config.typography) {
errors.push('Typography configuration is required');
}
// Validate format constraints (skip for Kindle)
if (!isKindle) {
if (config.format.width < 4 || config.format.width > 8.5) {
errors.push('Format width must be between 4" and 8.5"');
}
if (config.format.height < 6 || config.format.height > 11.69) {
errors.push('Format height must be between 6" and 11.69"');
}
}
return {
valid: errors.length === 0,
errors,
};
}
static getAvailableFormats() {
return Object.keys(this.KDP_FORMATS);
}
static getFormatByName(name) {
return this.KDP_FORMATS[name];
}
static createCustomFormat(name, width, height, unit = 'in') {
return {
name,
width,
height,
unit,
};
}
static getKindleMargins() {
// Kindle needs minimal margins as devices handle their own
return {
top: 0.5,
bottom: 0.5,
inside: 0.3,
outside: 0.3,
unit: 'in',
};
}
static getKindleTypography() {
// Kindle typography optimized for e-readers
const bodyFont = {
family: 'Georgia, serif', // Kindle defaults to serif fonts
size: 12, // Slightly larger for e-readers
lineHeight: 1.6, // More spacing for screen reading
weight: 'normal',
style: 'normal',
color: '#000000',
marginTop: 0,
marginBottom: 12,
};
return {
body: bodyFont,
heading1: {
family: 'Helvetica, Arial, sans-serif',
size: 24,
lineHeight: 1.3,
weight: 'bold',
style: 'normal',
color: '#000000',
marginTop: 24,
marginBottom: 18,
},
heading2: {
family: 'Helvetica, Arial, sans-serif',
size: 20,
lineHeight: 1.3,
weight: 'bold',
style: 'normal',
color: '#000000',
marginTop: 20,
marginBottom: 14,
},
heading3: {
family: 'Helvetica, Arial, sans-serif',
size: 16,
lineHeight: 1.3,
weight: 'bold',
style: 'normal',
color: '#000000',
marginTop: 18,
marginBottom: 12,
},
heading4: {
family: 'Helvetica, Arial, sans-serif',
size: 14,
lineHeight: 1.3,
weight: 'bold',
style: 'normal',
color: '#000000',
marginTop: 16,
marginBottom: 10,
},
heading5: {
family: 'Helvetica, Arial, sans-serif',
size: 13,
lineHeight: 1.3,
weight: 'bold',
style: 'normal',
color: '#000000',
marginTop: 14,
marginBottom: 8,
},
heading6: {
family: 'Helvetica, Arial, sans-serif',
size: 12,
lineHeight: 1.3,
weight: 'bold',
style: 'normal',
color: '#000000',
marginTop: 12,
marginBottom: 6,
},
};
}
static getKindlePageNumbers() {
// Kindle handles page numbers differently
return {
enabled: false, // Kindle uses location numbers
startPage: 1,
format: 'decimal',
position: 'footer',
alignment: 'center',
};
}
static mergeConfig(defaultConfig, userConfig) {
return {
...defaultConfig,
...userConfig,
format: userConfig.format || defaultConfig.format,
margins: { ...defaultConfig.margins, ...userConfig.margins },
typography: { ...defaultConfig.typography, ...userConfig.typography },
pageNumbers: { ...defaultConfig.pageNumbers, ...userConfig.pageNumbers },
};
}
static loadFromFile(_configPath) {
// This would load from JSON/YAML file
// For now, return default config
return this.getDefaultConfig();
}
static saveToFile(_config, _configPath) {
// This would save to JSON/YAML file
// Implementation depends on chosen format
}
}
exports.BookConfigManager = BookConfigManager;
BookConfigManager.KDP_FORMATS = {
'6x9': {
name: '6" x 9"',
width: 6,
height: 9,
unit: 'in',
},
'5.5x8.5': {
name: '5.5" x 8.5"',
width: 5.5,
height: 8.5,
unit: 'in',
},
'5x8': {
name: '5" x 8"',
width: 5,
height: 8,
unit: 'in',
},
'8.5x11': {
name: '8.5" x 11"',
width: 8.5,
height: 11,
unit: 'in',
},
'7x10': {
name: '7" x 10"',
width: 7,
height: 10,
unit: 'in',
},
'7.5x9.25': {
name: '7.5" x 9.25"',
width: 7.5,
height: 9.25,
unit: 'in',
},
kindle: {
name: 'Kindle',
width: 6,
height: 9,
unit: 'in',
},
};
//# sourceMappingURL=book-config.js.map