import { readFile } from 'node:fs/promises'; import { AImgParams, DefaultTemplates, escapeHtml, HtmlString, Path, Section, Strings, Structure } from './builder-model'; import { resolve } from 'node:path'; export interface ExtraStrings extends Strings { file: string; links: Record; sourceCodeAt: string; landingFile: string; landing: { subTitle: string; subscribeOn: string; updates: string[]; followOn: string; follow: string[]; supportThisWork: string; support: []; content: string[]; liveExamples: string; download: string; or: string; readOnline: string; license: string; footer: string[]; }; sidePanel: { shareTo: string; services: Array<{ key: string; link: string }>; shareParameters: Record; copyLink: string; shareLink: string; }; aboutMe: { title: string; imageCredit: string; content: string[]; }; subtitle: string; frontPage: { title: string; subtitle: string; contents: string[]; }; clickToEnlarge: string; imageCredit: string; } export class CustomTemplates extends DefaultTemplates { constructor( private readonly target: 'epub' | 'html' | 'pdf' | 'tex', ...args: ConstructorParameters> ) { super(...args); } htmlImprintPages() { return `

${this.strings.author}
${this.strings.frontPage.title} ${ this.strings.frontPage.subtitle ? `:
${this.strings.frontPage.subtitle}` : '
' }

${this.strings.author}. ${this.strings.title}${ this.strings.subtitle ? `: ${this.strings.subtitle}` : '' }.
${ this.strings.links.emailString } · ${ this.strings.links.linkedinString } · ${this.strings.links.substackString}

${this.strings.frontPage.contents.join('')}
`; } public async htmlAImgTitle(params: AImgParams) { return `
${escapeHtml(this.imageTitle(params))}${ params.size || (this.target !== 'html' && !params.href) ? '' : `${ (params.title.at(-1) ?? '').match(/[\.\?\!\)]/) ? ' ' : '. ' }${await this.htmlAImgRef(params)}
` }` as HtmlString; } public async htmlAImgRef(params: AImgParams) { return params.href ? `${this.string('imageCredit')}: ${ params.alt }` : `${ this.strings.clickToEnlarge }`; } public async htmlAImgImage(params: AImgParams) { return params.size || this.target !== 'html' ? super.htmlAImgImage(params) : (`${await super.htmlAImgImage( params )}` as HtmlString); } public async htmlBody(body: string, structure: Structure) { return `${await this.htmlSidePanel( structure )}
${body}
${await this.htmlMainScript()}` as HtmlString; } public async htmlSection(section: Section) { if (section.getCounter() === 1) { return `${await super.htmlSection(section)}` as HtmlString; } else { return super.htmlSection(section); } } public async htmlSidePanel(structure: Structure) { return ` `; } public async htmlMainScript() { return ``; } public async htmlShareControl() { const sidePanel = this.strings.sidePanel; return ``; } } export interface Example { name: string; path: Path; } export const toc = async ( { structure, strings, templates, lang }: { structure: Structure; strings: ExtraStrings; templates: CustomTemplates; lang: string; }, examples: Example[] ) => { const link = linker(strings, lang); return ``; }; export const shareLinks = (strings: ExtraStrings) => `${strings.sidePanel.services .map( ({ key, link }) => `` ) .join(' · ')}`; export const shareLink = (link: string, parameters: Record) => { let result = link; for (const [key, value] of Object.entries(parameters)) { result = result.replace( new RegExp(`\\$\\{${key}\\}`, 'g'), encodeURIComponent(value) ); } return result; }; export const linker = (strings: ExtraStrings, lang: string) => (anchor?: string, type = 'html') => `${encodeURIComponent(strings.file)}.${lang}.${type}${ anchor ? '#' + anchor : '' }`;