95 lines
3.1 KiB
TypeScript
95 lines
3.1 KiB
TypeScript
import { AbstractElement } from './elements/abstract-element';
|
|
import { AbstractBuilder } from './abstract-builder';
|
|
import { saveAs } from 'file-saver';
|
|
import {
|
|
HTML_LABEL_SIZE,
|
|
HTML_TEXT_SIZE,
|
|
i18n,
|
|
LABEL_SIZE,
|
|
TEXT_SIZE,
|
|
} from './constants';
|
|
import { GenerateTypeEnum } from './elements/generate-type.enum';
|
|
|
|
export class HtmlBuilder extends AbstractBuilder {
|
|
public doc: Document;
|
|
public styleSheet: HTMLStyleElement;
|
|
|
|
constructor() {
|
|
super();
|
|
this.doc = document.implementation.createHTMLDocument();
|
|
const style = document.createElement('style');
|
|
style.innerHTML = '.column { display: flex; flex-direction: column; }';
|
|
style.innerHTML += ' .main-column { align-items: center; }';
|
|
style.innerHTML += ' .row { display: flex; flex-direction: row }';
|
|
style.innerHTML += ' .row:not(.labelled-value) { gap: 5em; }';
|
|
style.innerHTML +=
|
|
' .row.labelled-value { gap: 10px; justify-content: space-between; }';
|
|
style.innerHTML +=
|
|
' .separator { border: 1px solid; width: 100%; height: 0px }';
|
|
style.appendChild(document.createTextNode(''));
|
|
this.doc.head.appendChild(style);
|
|
this.styleSheet = style;
|
|
const meta1 = document.createElement('meta');
|
|
meta1.setAttribute('charset', 'UTF-8');
|
|
this.doc.head.appendChild(meta1);
|
|
const meta2 = document.createElement('meta');
|
|
meta2.setAttribute('name', 'viewport');
|
|
meta2.setAttribute(
|
|
'content',
|
|
'width=device-width, initial-scale=1, maximum-scale=1, user-scalable=yes'
|
|
);
|
|
this.doc.head.appendChild(meta2);
|
|
}
|
|
|
|
public getLabelledRowHeight(): number {
|
|
return 0;
|
|
}
|
|
|
|
public save(name: string) {
|
|
this.doc.title = name;
|
|
const blob = new Blob(
|
|
[
|
|
`<html lang="${i18n().lang}">
|
|
${this.doc.documentElement.innerHTML}
|
|
</html>`,
|
|
],
|
|
{ type: 'text/html;charset=utf-8' }
|
|
);
|
|
saveAs(blob, `${name}.html`);
|
|
}
|
|
|
|
public build(elements: AbstractElement[]) {
|
|
const cssList: string[] = [];
|
|
for (const element of elements.filter((el) => el.context.isHtml)) {
|
|
element.renderHtml(this.doc, this.doc.body, cssList, this.styleSheet);
|
|
}
|
|
// Mobile start
|
|
this.styleSheet.innerHTML += ' @media screen and (max-width: 959px) {';
|
|
this.styleSheet.innerHTML += ` .text-${TEXT_SIZE} { font-size: ${
|
|
2 * HTML_TEXT_SIZE
|
|
}rem; }`;
|
|
this.styleSheet.innerHTML += ` .labelled-text > .text-${TEXT_SIZE} { font-size: ${
|
|
2 * HTML_TEXT_SIZE
|
|
}rem; margin: 0; }`;
|
|
this.styleSheet.innerHTML += ` .label-${LABEL_SIZE} { font-size: ${
|
|
2 * HTML_LABEL_SIZE
|
|
}rem; }`;
|
|
this.styleSheet.innerHTML +=
|
|
' .main-column { align-items: stretch; overflow-x: hidden; }';
|
|
this.styleSheet.innerHTML +=
|
|
' .row:not(.labelled-value) { flex-wrap: wrap; gap: 0 5em; }';
|
|
this.styleSheet.innerHTML += ' .skills { width: 100%; }';
|
|
this.styleSheet.innerHTML += ' .skills-column { width: 100%; }';
|
|
this.styleSheet.innerHTML += ' }';
|
|
// Mobile end
|
|
}
|
|
|
|
public getImageScale(): number {
|
|
return 4;
|
|
}
|
|
|
|
public getGenerateType(): GenerateTypeEnum {
|
|
return GenerateTypeEnum.HTML;
|
|
}
|
|
}
|