legal-markdown-js
Version:
Node.js implementation of LegalMarkdown for processing legal documents with markdown and YAML - Complete feature parity with Ruby version
111 lines • 4.38 kB
JavaScript
/**
* Default Legal Markdown configuration values.
*
* @example
* ```ts
* import { DEFAULT_CONFIG } from './schema.js';
*
* console.log(DEFAULT_CONFIG.pdf.connector); // "auto"
* ```
*/
export const DEFAULT_CONFIG = {
paths: {
images: '.',
styles: '.',
input: '.',
output: '.',
archive: '.',
},
logging: {
level: 'error',
debug: false,
},
processing: {
highlight: false,
enableFieldTracking: false,
astFieldTracking: false,
logicBranchHighlighting: false,
validationMode: 'auto',
locale: Intl.DateTimeFormat().resolvedOptions().locale,
},
pdf: {
connector: 'auto',
format: 'A4',
margin: {
top: '1in',
bottom: '1in',
left: '1in',
right: '1in',
},
},
};
const LOG_LEVELS = new Set(['error', 'warn', 'info', 'debug']);
const VALIDATION_MODES = new Set([
'strict',
'permissive',
'auto',
]);
const PDF_CONNECTORS = new Set([
'auto',
'puppeteer',
'system-chrome',
'weasyprint',
]);
const PDF_FORMATS = new Set(['A4', 'Letter']);
function asNonEmptyString(value, fallback) {
return typeof value === 'string' && value.trim() ? value.trim() : fallback;
}
function asBoolean(value, fallback) {
return typeof value === 'boolean' ? value : fallback;
}
function asEnum(value, allowed, fallback, fieldName, errors) {
if (value === undefined)
return fallback;
if (typeof value !== 'string' || !allowed.has(value)) {
errors.push(`${fieldName} must be one of: ${Array.from(allowed).join(', ')}`);
return fallback;
}
return value;
}
export function validateConfig(config) {
const errors = [];
const candidate = (config ?? {});
const validated = {
paths: {
images: asNonEmptyString(candidate.paths?.images, DEFAULT_CONFIG.paths.images),
styles: asNonEmptyString(candidate.paths?.styles, DEFAULT_CONFIG.paths.styles),
input: asNonEmptyString(candidate.paths?.input, DEFAULT_CONFIG.paths.input),
output: asNonEmptyString(candidate.paths?.output, DEFAULT_CONFIG.paths.output),
archive: asNonEmptyString(candidate.paths?.archive, DEFAULT_CONFIG.paths.archive),
},
logging: {
level: asEnum(candidate.logging?.level, LOG_LEVELS, DEFAULT_CONFIG.logging.level, 'logging.level', errors),
debug: asBoolean(candidate.logging?.debug, DEFAULT_CONFIG.logging.debug),
},
processing: {
highlight: asBoolean(candidate.processing?.highlight, DEFAULT_CONFIG.processing.highlight),
enableFieldTracking: asBoolean(candidate.processing?.enableFieldTracking, DEFAULT_CONFIG.processing.enableFieldTracking),
astFieldTracking: asBoolean(candidate.processing?.astFieldTracking, DEFAULT_CONFIG.processing.astFieldTracking),
logicBranchHighlighting: asBoolean(candidate.processing?.logicBranchHighlighting, DEFAULT_CONFIG.processing.logicBranchHighlighting),
validationMode: asEnum(candidate.processing?.validationMode, VALIDATION_MODES, DEFAULT_CONFIG.processing.validationMode, 'processing.validationMode', errors),
locale: asNonEmptyString(candidate.processing?.locale, DEFAULT_CONFIG.processing.locale),
},
pdf: {
connector: asEnum(candidate.pdf?.connector, PDF_CONNECTORS, DEFAULT_CONFIG.pdf.connector, 'pdf.connector', errors),
format: asEnum(candidate.pdf?.format, PDF_FORMATS, DEFAULT_CONFIG.pdf.format, 'pdf.format', errors),
margin: {
top: asNonEmptyString(candidate.pdf?.margin?.top, DEFAULT_CONFIG.pdf.margin.top),
bottom: asNonEmptyString(candidate.pdf?.margin?.bottom, DEFAULT_CONFIG.pdf.margin.bottom),
left: asNonEmptyString(candidate.pdf?.margin?.left, DEFAULT_CONFIG.pdf.margin.left),
right: asNonEmptyString(candidate.pdf?.margin?.right, DEFAULT_CONFIG.pdf.margin.right),
},
},
};
if (errors.length > 0) {
throw new Error(`Invalid legal-md configuration:\n${errors.map(error => `- ${error}`).join('\n')}`);
}
return validated;
}
// Exported for testing - not part of public API
export { asEnum as _asEnum };
//# sourceMappingURL=schema.js.map