Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7279b93e4c | ||
|
|
1d940892d7 | ||
|
|
612ed7b631 | ||
|
|
fcd74152bb | ||
|
|
3451c86b36 | ||
|
|
fc49c91024 | ||
|
|
c3c4027511 | ||
|
|
a0fffb6cf7 | ||
|
|
f9c1045557 | ||
|
|
b759c032a8 | ||
|
|
851bc738e5 | ||
|
|
049c77a004 | ||
|
|
b16967c351 | ||
|
|
986d50a5eb | ||
|
|
a246f899f4 | ||
|
|
b5c6b5510e |
@@ -4,11 +4,11 @@ variables:
|
||||
|
||||
include:
|
||||
- project: '$CI_PROJECT_ROOT_NAMESPACE/ci-tools/pipeline/ci-tools-pipeline-release'
|
||||
ref: 1.0.0
|
||||
ref: 2.0.0
|
||||
file: '/release-common.yml'
|
||||
- project: '$CI_PROJECT_ROOT_NAMESPACE/ci-tools/pipeline/ci-tools-pipeline-release-node'
|
||||
ref: 1.0.1
|
||||
ref: 1.0.2
|
||||
file: '/release-node.yml'
|
||||
- project: '$CI_PROJECT_ROOT_NAMESPACE/ci-tools/pipeline/ci-tools-pipeline-project-foundry-module'
|
||||
ref: 1.0.1
|
||||
ref: 1.1.0
|
||||
file: '/pipeline-foundry-module.yml'
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
## In development
|
||||
|
||||
## 1.2.0
|
||||
|
||||
### New features
|
||||
|
||||
- HTML Responsive Export Characters sheet
|
||||
- Add contextual menu to actor to HTML responsive Export Characters sheet
|
||||
|
||||
## 1.1.0
|
||||
|
||||
- Add contextual menu to actor to PDF Export Characters sheet
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# WFRP 4 Actor Sheet Print
|
||||
|
||||
This module allow to export characters sheet on a friendly print pdf.
|
||||
This module allow to export characters sheet on a friendly print pdf or a responsive html.
|
||||
|
||||
# Authors
|
||||
|
||||
@@ -28,7 +28,7 @@ A print buton is added on top of sheet to export as pdf
|
||||
|
||||

|
||||
|
||||
A Contextual menu is added on Actor menu
|
||||
A Contextual menu is added on Actor menu, one for pdf, an other for html
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
{
|
||||
"WFRP4SHEETPRINT.export.pdf": "Export to PDF"
|
||||
"WFRP4SHEETPRINT.export.pdf": "Export to PDF",
|
||||
"WFRP4SHEETPRINT.export.html": "Export to Html"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
{
|
||||
"WFRP4SHEETPRINT.export.pdf": "Exporter en PDF"
|
||||
"WFRP4SHEETPRINT.export.pdf": "Exporter en PDF",
|
||||
"WFRP4SHEETPRINT.export.html": "Exporter en Html"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
cp -r ./dist/* $LOCAL_FOUNDRY
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 83 KiB |
36
module.json
36
module.json
@@ -1,24 +1,44 @@
|
||||
{
|
||||
"name": "wfrp4e-actor-sheet-print",
|
||||
"id": "wfrp4e-actor-sheet-print",
|
||||
"title": "[WFRP4] Actor Sheet Print",
|
||||
"description": "Functions to print actor sheet",
|
||||
"version": "${MODULE_VERSION}",
|
||||
"minimumCoreVersion": "0.8.0",
|
||||
"compatibleCoreVersion": "9",
|
||||
"author": "Skeroujvapluvit",
|
||||
"systems": ["wfrp4e"],
|
||||
"dependencies": [],
|
||||
"compatibility": {
|
||||
"minimum": "10",
|
||||
"verified": "11.315",
|
||||
"maximum": "11"
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "Skeroujvapluvit",
|
||||
"flags": {}
|
||||
}
|
||||
],
|
||||
"relationships": {
|
||||
"systems": [
|
||||
{
|
||||
"id": "wfrp4e",
|
||||
"type": "system",
|
||||
"compatibility": {
|
||||
"verified": "6.5.9"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requires": []
|
||||
},
|
||||
"esmodules": ["main.js"],
|
||||
"languages": [
|
||||
{
|
||||
"lang": "en",
|
||||
"name": "English",
|
||||
"path": "lang/en.json"
|
||||
"path": "lang/en.json",
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"name": "Français",
|
||||
"path": "lang/fr.json"
|
||||
"path": "lang/fr.json",
|
||||
"flags": {}
|
||||
}
|
||||
],
|
||||
"styles": ["./styles/main.css"],
|
||||
|
||||
13
package-lock.json
generated
13
package-lock.json
generated
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.0.4",
|
||||
"version": "3.0.1",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -519,6 +519,12 @@
|
||||
"integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/file-saver": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.5.tgz",
|
||||
"integrity": "sha512-zv9kNf3keYegP5oThGLaPk8E081DFDuwfqjtiTzm6PoxChdJ1raSuADf2YGCVIyrSynLrgc8JWv296s7Q7pQSQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/jquery": {
|
||||
"version": "3.5.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.11.tgz",
|
||||
@@ -1224,6 +1230,11 @@
|
||||
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz",
|
||||
"integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA=="
|
||||
},
|
||||
"file-saver": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
|
||||
"integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"build": "webpack",
|
||||
"local-deploy": "npm run package && sh ./local-deploy.sh"
|
||||
},
|
||||
"version": "1.1.0",
|
||||
"version": "3.0.1",
|
||||
"devDependencies": {
|
||||
"@league-of-foundry-developers/foundry-vtt-types": "0.8.9-9",
|
||||
"husky": "4.3.7",
|
||||
@@ -14,7 +14,8 @@
|
||||
"typescript": "4.5.4",
|
||||
"ts-loader": "9.2.6",
|
||||
"webpack": "5.65.0",
|
||||
"webpack-cli": "4.9.1"
|
||||
"webpack-cli": "4.9.1",
|
||||
"@types/file-saver": "2.0.5"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
@@ -22,6 +23,7 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"jspdf": "2.4.0"
|
||||
"jspdf": "2.4.0",
|
||||
"file-saver": "2.0.5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
rm -fr dist
|
||||
npm run build
|
||||
cp -r $MODULE_DIRS dist/
|
||||
|
||||
14
src/abstract-builder.ts
Normal file
14
src/abstract-builder.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { AbstractElement } from './elements/abstract-element';
|
||||
import { GenerateTypeEnum } from './elements/generate-type.enum';
|
||||
|
||||
export abstract class AbstractBuilder {
|
||||
public abstract build(elements: AbstractElement[]);
|
||||
|
||||
public abstract getLabelledRowHeight(): number;
|
||||
|
||||
public abstract save(name: string);
|
||||
|
||||
public abstract getImageScale(): number;
|
||||
|
||||
public abstract getGenerateType(): GenerateTypeEnum;
|
||||
}
|
||||
@@ -6,4 +6,6 @@ export const isGM = () => user()?.isGM ?? false;
|
||||
|
||||
export const TEXT_SIZE = 8;
|
||||
export const LABEL_SIZE = 6;
|
||||
export const HTML_TEXT_SIZE = 1;
|
||||
export const HTML_LABEL_SIZE = 0.75;
|
||||
export const MARGINS = { top: 10, left: 10, bottom: 10, right: 10 };
|
||||
|
||||
38
src/elements/abstract-container-element.ts
Normal file
38
src/elements/abstract-container-element.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { AbstractElement } from './abstract-element';
|
||||
import { IContext } from './context';
|
||||
import { GenerateTypeEnum } from './generate-type.enum';
|
||||
|
||||
export abstract class AbstractContainerElement extends AbstractElement {
|
||||
public pdfElements: AbstractElement[] = [];
|
||||
public htmlElements: AbstractElement[] = [];
|
||||
public contextElements: AbstractElement[] = [];
|
||||
|
||||
constructor(
|
||||
globalType: GenerateTypeEnum,
|
||||
x: number,
|
||||
y: number,
|
||||
maxWidth: number | undefined,
|
||||
elements: AbstractElement[] = [],
|
||||
context: Partial<IContext> = AbstractElement.DEFAULT_CONTEXT
|
||||
) {
|
||||
super(globalType, x, y, maxWidth, context);
|
||||
this.htmlElements = this.context.isHtml
|
||||
? elements.filter((el) => el.context.isHtml)
|
||||
: [];
|
||||
this.pdfElements = this.context.isPdf
|
||||
? elements.filter((el) => el.context.isPdf)
|
||||
: [];
|
||||
this.contextElements =
|
||||
this.globalType === GenerateTypeEnum.HTML
|
||||
? this.htmlElements
|
||||
: this.pdfElements;
|
||||
}
|
||||
|
||||
public getElements(): AbstractElement[] {
|
||||
const elements: AbstractElement[] = [];
|
||||
for (const element of this.contextElements) {
|
||||
elements.push(...element.getElements());
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,36 @@
|
||||
import jsPDF from 'jspdf';
|
||||
import { MARGINS } from '../constants';
|
||||
import { IContext } from './context';
|
||||
import { GenerateTypeEnum } from './generate-type.enum';
|
||||
|
||||
export abstract class AbstractElement {
|
||||
public static readonly DEFAULT_CONTEXT: IContext = {
|
||||
isHtml: true,
|
||||
isPdf: true,
|
||||
name: 'element',
|
||||
};
|
||||
|
||||
public globalType: GenerateTypeEnum;
|
||||
public x: number;
|
||||
public y: number;
|
||||
public maxWidth?: number;
|
||||
public context: IContext = AbstractElement.DEFAULT_CONTEXT;
|
||||
|
||||
constructor(x: number, y: number, maxWidth?: number | undefined) {
|
||||
constructor(
|
||||
globalType: GenerateTypeEnum,
|
||||
x: number,
|
||||
y: number,
|
||||
maxWidth?: number | undefined,
|
||||
context: Partial<IContext> = AbstractElement.DEFAULT_CONTEXT
|
||||
) {
|
||||
this.globalType = globalType;
|
||||
this.x = x >= MARGINS.left ? x : MARGINS.left;
|
||||
this.y = y >= MARGINS.top ? y : MARGINS.top;
|
||||
this.maxWidth = maxWidth;
|
||||
this.context = {
|
||||
...this.context,
|
||||
...context,
|
||||
};
|
||||
}
|
||||
|
||||
public getHeightFromPx(doc: jsPDF, size: number) {
|
||||
@@ -28,6 +49,13 @@ export abstract class AbstractElement {
|
||||
|
||||
public abstract render(doc: jsPDF, maxWidth?: number): jsPDF;
|
||||
|
||||
public abstract renderHtml(
|
||||
doc: Document,
|
||||
parent: HTMLElement,
|
||||
cssRules: string[],
|
||||
sheet: HTMLStyleElement
|
||||
): Document;
|
||||
|
||||
public abstract getHeight(doc?: jsPDF): number;
|
||||
|
||||
public abstract getCheckNewPageHeight(doc?: jsPDF): number;
|
||||
|
||||
@@ -1,14 +1,23 @@
|
||||
import { AbstractElement } from './abstract-element';
|
||||
import jsPDF from 'jspdf';
|
||||
import { Box } from './box';
|
||||
import { IContext } from './context';
|
||||
import { GenerateTypeEnum } from './generate-type.enum';
|
||||
|
||||
export class Blank extends Box {
|
||||
constructor(x: number, y: number, w: number, h: number) {
|
||||
super(x, y, w, h);
|
||||
constructor(
|
||||
globalType: GenerateTypeEnum,
|
||||
x: number,
|
||||
y: number,
|
||||
w: number,
|
||||
h: number,
|
||||
context: Partial<IContext> = AbstractElement.DEFAULT_CONTEXT
|
||||
) {
|
||||
super(globalType, x, y, w, h, context);
|
||||
}
|
||||
|
||||
public static heightBlank(h: number) {
|
||||
return new Blank(0, 0, 0, h);
|
||||
public static heightBlank(globalType: GenerateTypeEnum, h: number) {
|
||||
return new Blank(globalType, 0, 0, 0, h);
|
||||
}
|
||||
|
||||
public getCheckNewPageHeight(doc?: jsPDF): number {
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
import { AbstractElement } from './abstract-element';
|
||||
import jsPDF from 'jspdf';
|
||||
import { IContext } from './context';
|
||||
import { GenerateTypeEnum } from './generate-type.enum';
|
||||
|
||||
export class Box extends AbstractElement {
|
||||
public w: number;
|
||||
public h: number;
|
||||
|
||||
constructor(x: number, y: number, w: number, h: number) {
|
||||
super(x, y, w);
|
||||
constructor(
|
||||
globalType: GenerateTypeEnum,
|
||||
x: number,
|
||||
y: number,
|
||||
w: number,
|
||||
h: number,
|
||||
context: Partial<IContext> = AbstractElement.DEFAULT_CONTEXT
|
||||
) {
|
||||
super(globalType, x, y, w, context);
|
||||
this.w = w;
|
||||
this.h = h;
|
||||
}
|
||||
@@ -20,6 +29,34 @@ export class Box extends AbstractElement {
|
||||
return doc;
|
||||
}
|
||||
|
||||
public renderHtml(
|
||||
doc: Document,
|
||||
parent: HTMLElement,
|
||||
cssRules: string[],
|
||||
sheet: HTMLStyleElement
|
||||
): Document {
|
||||
const div = doc.createElement('div');
|
||||
const css = `box-${this.w ?? 0}-${this.h ?? 0}`;
|
||||
div.classList.add(`box`);
|
||||
div.classList.add(css);
|
||||
div.classList.add(this.context.name);
|
||||
if (!cssRules.includes(css)) {
|
||||
cssRules.push(css);
|
||||
let rule = 'width: 100%;';
|
||||
if (this.w > 0) {
|
||||
rule += `max-width: ${this.w}px;`;
|
||||
rule += `min-width: ${this.w}px;`;
|
||||
}
|
||||
if (this.h > 0) {
|
||||
rule += `max-height: ${this.h}px;`;
|
||||
rule += `min-height: ${this.h}px;`;
|
||||
}
|
||||
sheet.innerHTML += ` .${css} { ${rule} }`;
|
||||
}
|
||||
parent.append(div);
|
||||
return doc;
|
||||
}
|
||||
|
||||
public getHeight(_doc): number {
|
||||
return this.h;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
import { AbstractElement } from './abstract-element';
|
||||
import jsPDF from 'jspdf';
|
||||
import { IContext } from './context';
|
||||
import { AbstractContainerElement } from './abstract-container-element';
|
||||
import { GenerateTypeEnum } from './generate-type.enum';
|
||||
|
||||
export class Column extends AbstractElement {
|
||||
public elements: AbstractElement[] = [];
|
||||
|
||||
constructor(x: number, y: number, elements: AbstractElement[]) {
|
||||
super(x, y);
|
||||
this.elements = elements;
|
||||
export class Column extends AbstractContainerElement {
|
||||
constructor(
|
||||
globalType: GenerateTypeEnum,
|
||||
x: number,
|
||||
y: number,
|
||||
elements: AbstractElement[],
|
||||
context: Partial<IContext> = AbstractElement.DEFAULT_CONTEXT
|
||||
) {
|
||||
super(globalType, x, y, undefined, elements, context);
|
||||
}
|
||||
|
||||
public prepareRender(doc: jsPDF, _maxWidth?: number): jsPDF {
|
||||
const elements = this.elements ?? [];
|
||||
const elements = this.pdfElements ?? [];
|
||||
|
||||
let currentY = this.y;
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
@@ -29,9 +35,27 @@ export class Column extends AbstractElement {
|
||||
return doc;
|
||||
}
|
||||
|
||||
public renderHtml(
|
||||
doc: Document,
|
||||
parent: HTMLElement,
|
||||
cssRules: string[],
|
||||
sheet: HTMLStyleElement
|
||||
): Document {
|
||||
const div = doc.createElement('div');
|
||||
div.classList.add(`column`);
|
||||
div.classList.add(this.context.name);
|
||||
const elements = this.htmlElements ?? [];
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
const element = elements[i];
|
||||
element.renderHtml(doc, div, cssRules, sheet);
|
||||
}
|
||||
parent.append(div);
|
||||
return doc;
|
||||
}
|
||||
|
||||
public getHeight(doc): number {
|
||||
return this.elements.length > 0
|
||||
? this.elements
|
||||
return this.pdfElements.length > 0
|
||||
? this.pdfElements
|
||||
.map((e) => e.getHeight(doc))
|
||||
.reduce((p, c, i) => {
|
||||
if (i === 0) {
|
||||
@@ -43,20 +67,8 @@ export class Column extends AbstractElement {
|
||||
}
|
||||
|
||||
public getCheckNewPageHeight(doc?: jsPDF): number {
|
||||
return this.elements.length > 0
|
||||
? this.elements[0].getCheckNewPageHeight(doc)
|
||||
return this.pdfElements.length > 0
|
||||
? this.pdfElements[0].getCheckNewPageHeight(doc)
|
||||
: 0;
|
||||
}
|
||||
|
||||
public getElements(): AbstractElement[] {
|
||||
const elements: AbstractElement[] = [];
|
||||
for (const element of this.elements) {
|
||||
elements.push(...element.getElements());
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
public isEmpty(): boolean {
|
||||
return this.elements.length === 0;
|
||||
}
|
||||
}
|
||||
|
||||
5
src/elements/context.ts
Normal file
5
src/elements/context.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export interface IContext {
|
||||
name: string;
|
||||
isHtml: boolean;
|
||||
isPdf: boolean;
|
||||
}
|
||||
4
src/elements/generate-type.enum.ts
Normal file
4
src/elements/generate-type.enum.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export enum GenerateTypeEnum {
|
||||
PDF = 'PDF',
|
||||
HTML = 'HTML',
|
||||
}
|
||||
@@ -1,12 +1,22 @@
|
||||
import { Box } from './box';
|
||||
import jsPDF from 'jspdf';
|
||||
import { AbstractElement } from './abstract-element';
|
||||
import { IContext } from './context';
|
||||
import { GenerateTypeEnum } from './generate-type.enum';
|
||||
|
||||
export class Image extends Box {
|
||||
public imageData: string;
|
||||
|
||||
constructor(x: number, y: number, w: number, h: number, imageData: string) {
|
||||
super(x, y, w, h);
|
||||
constructor(
|
||||
globalType: GenerateTypeEnum,
|
||||
x: number,
|
||||
y: number,
|
||||
w: number,
|
||||
h: number,
|
||||
imageData: string,
|
||||
context: Partial<IContext> = AbstractElement.DEFAULT_CONTEXT
|
||||
) {
|
||||
super(globalType, x, y, w, h, context);
|
||||
this.imageData = imageData;
|
||||
}
|
||||
|
||||
@@ -21,6 +31,32 @@ export class Image extends Box {
|
||||
return doc;
|
||||
}
|
||||
|
||||
public renderHtml(
|
||||
doc: Document,
|
||||
parent: HTMLElement,
|
||||
cssRules: string[],
|
||||
sheet: HTMLStyleElement
|
||||
): Document {
|
||||
const img = doc.createElement('img');
|
||||
img.src = this.imageData;
|
||||
const css = `img-${this.w ?? 0}`;
|
||||
img.classList.add(`img`);
|
||||
img.classList.add(css);
|
||||
img.classList.add(this.context.name);
|
||||
if (!cssRules.includes(css)) {
|
||||
cssRules.push(css);
|
||||
let rule = '';
|
||||
if (this.w > 0) {
|
||||
rule += `width: ${this.w}px;`;
|
||||
}
|
||||
if (rule.length > 0) {
|
||||
sheet.innerHTML += ` .${css} { ${rule} }`;
|
||||
}
|
||||
}
|
||||
parent.append(img);
|
||||
return doc;
|
||||
}
|
||||
|
||||
public getElements(): AbstractElement[] {
|
||||
return [this];
|
||||
}
|
||||
|
||||
@@ -1,21 +1,31 @@
|
||||
import jsPDF, { TextOptionsLight } from 'jspdf';
|
||||
import { Text } from './text';
|
||||
import { i18nLocalize, LABEL_SIZE, TEXT_SIZE } from '../constants';
|
||||
import {
|
||||
HTML_LABEL_SIZE,
|
||||
HTML_TEXT_SIZE,
|
||||
i18nLocalize,
|
||||
LABEL_SIZE,
|
||||
TEXT_SIZE,
|
||||
} from '../constants';
|
||||
import { AbstractElement } from './abstract-element';
|
||||
import { IContext } from './context';
|
||||
import { GenerateTypeEnum } from './generate-type.enum';
|
||||
|
||||
export class LabelledText extends Text {
|
||||
public label: string;
|
||||
public labelOptions?: TextOptionsLight;
|
||||
|
||||
constructor(
|
||||
globalType: GenerateTypeEnum,
|
||||
x: number,
|
||||
y: number,
|
||||
label: string,
|
||||
text: string,
|
||||
textOptions?: TextOptionsLight,
|
||||
labelOptions?: TextOptionsLight
|
||||
labelOptions?: TextOptionsLight,
|
||||
context: Partial<IContext> = AbstractElement.DEFAULT_CONTEXT
|
||||
) {
|
||||
super(x, y, text, textOptions);
|
||||
super(globalType, x, y, text, textOptions, context);
|
||||
this.label = label;
|
||||
this.labelOptions = labelOptions;
|
||||
const textMaxWidth = this.textOptions?.maxWidth ?? 0;
|
||||
@@ -40,6 +50,40 @@ export class LabelledText extends Text {
|
||||
return doc;
|
||||
}
|
||||
|
||||
public renderHtml(
|
||||
doc: Document,
|
||||
parent: HTMLElement,
|
||||
cssRules: string[],
|
||||
sheet: HTMLStyleElement
|
||||
): Document {
|
||||
const div = doc.createElement('div');
|
||||
div.classList.add(`column`);
|
||||
div.classList.add(`labelled-text`);
|
||||
div.classList.add(this.context.name);
|
||||
const label = doc.createElement('p');
|
||||
const text = doc.createElement('p');
|
||||
const labelCss = `label-${LABEL_SIZE}`;
|
||||
const textCss = `text-${TEXT_SIZE}`;
|
||||
label.classList.add(labelCss);
|
||||
text.classList.add(textCss);
|
||||
if (!cssRules.includes(labelCss)) {
|
||||
cssRules.push(labelCss);
|
||||
sheet.innerHTML += ` .${labelCss} { font-size: ${HTML_LABEL_SIZE}rem; margin: 0; }`;
|
||||
}
|
||||
if (!cssRules.includes(textCss)) {
|
||||
cssRules.push(textCss);
|
||||
sheet.innerHTML += ` .${textCss} { font-size: ${HTML_TEXT_SIZE}rem; margin-top: 0.5rem; margin-bottom: 0.5rem; }`;
|
||||
sheet.innerHTML += ` .labelled-text { margin-top: 0.5rem; margin-bottom: 0.5rem; }`;
|
||||
sheet.innerHTML += ` .labelled-text > .${textCss} { font-size: ${HTML_TEXT_SIZE}rem; margin: 0; }`;
|
||||
}
|
||||
label.innerHTML = i18nLocalize(this.label);
|
||||
text.innerHTML = i18nLocalize(this.text);
|
||||
div.append(label);
|
||||
div.append(text);
|
||||
parent.append(div);
|
||||
return doc;
|
||||
}
|
||||
|
||||
protected updateMaxWidth(maxWidth?: number) {
|
||||
if (maxWidth != null && maxWidth > 0) {
|
||||
this.maxWidth = maxWidth;
|
||||
|
||||
@@ -1,32 +1,52 @@
|
||||
import { Row } from './row';
|
||||
import { Text } from './text';
|
||||
import { MultilineText } from './multiline-text';
|
||||
import { IContext } from './context';
|
||||
import { AbstractElement } from './abstract-element';
|
||||
import { GenerateTypeEnum } from './generate-type.enum';
|
||||
|
||||
export class LabelledValue extends Row {
|
||||
public label: string;
|
||||
public value: number;
|
||||
|
||||
constructor(
|
||||
globalType: GenerateTypeEnum,
|
||||
label: string,
|
||||
value: number,
|
||||
widthPercents?: number[],
|
||||
multiline = false,
|
||||
maxWidth?: number
|
||||
maxWidth?: number,
|
||||
context: Partial<IContext> = AbstractElement.DEFAULT_CONTEXT
|
||||
) {
|
||||
super(
|
||||
globalType,
|
||||
0,
|
||||
0,
|
||||
[
|
||||
multiline ? new MultilineText(0, 0, label) : new Text(0, 0, label),
|
||||
new Text(0, 0, value.toString(), {
|
||||
multiline
|
||||
? new MultilineText(globalType, 0, 0, label)
|
||||
: new Text(globalType, 0, 0, label),
|
||||
new Text(globalType, 0, 0, value.toString(), {
|
||||
align: 'right',
|
||||
}),
|
||||
],
|
||||
maxWidth,
|
||||
widthPercents,
|
||||
[]
|
||||
[],
|
||||
context
|
||||
);
|
||||
this.label = label;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public renderHtml(
|
||||
doc: Document,
|
||||
parent: HTMLElement,
|
||||
cssRules: string[],
|
||||
sheet: HTMLStyleElement
|
||||
): Document {
|
||||
const resultDoc = super.renderHtml(doc, parent, cssRules, sheet);
|
||||
parent.lastElementChild?.classList?.add('labelled-value');
|
||||
return resultDoc;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,19 +3,24 @@ import { Column } from './column';
|
||||
import { LabelledValue } from './labelled-value';
|
||||
import jsPDF from 'jspdf';
|
||||
import { MARGINS } from '../constants';
|
||||
import { IContext } from './context';
|
||||
import { AbstractElement } from './abstract-element';
|
||||
import { GenerateTypeEnum } from './generate-type.enum';
|
||||
|
||||
export class LabelledValues extends Row {
|
||||
public labelledValues: { label: string; value: number }[];
|
||||
public nbrOfCol: number;
|
||||
|
||||
constructor(
|
||||
globalType: GenerateTypeEnum,
|
||||
x: number,
|
||||
y: number,
|
||||
labelledValues: { label: string; value: number }[],
|
||||
nbrOfCol?: number,
|
||||
multiline = false
|
||||
multiline = false,
|
||||
context: Partial<IContext> = AbstractElement.DEFAULT_CONTEXT
|
||||
) {
|
||||
super(x, y, []);
|
||||
super(globalType, x, y, [], undefined, undefined, undefined, context);
|
||||
this.labelledValues = labelledValues;
|
||||
this.nbrOfCol = nbrOfCol ?? 3;
|
||||
if (this.nbrOfCol > 3) {
|
||||
@@ -35,7 +40,9 @@ export class LabelledValues extends Row {
|
||||
rest > 2 ? nbrPerCol + 1 : nbrPerCol,
|
||||
];
|
||||
for (let i = 0; i < this.nbrOfCol; i++) {
|
||||
this.elements[i] = new Column(0, 0, []);
|
||||
this.contextElements[i] = new Column(globalType, 0, 0, [], {
|
||||
name: `${this.context.name}-column`,
|
||||
});
|
||||
}
|
||||
for (let i = 0; i < labelledValues.length; i++) {
|
||||
if (i < nbrPerCols[0]) {
|
||||
@@ -45,8 +52,9 @@ export class LabelledValues extends Row {
|
||||
} else {
|
||||
currentIndex = 2;
|
||||
}
|
||||
(<Column>this.elements[currentIndex]).elements.push(
|
||||
(<Column>this.contextElements[currentIndex]).contextElements.push(
|
||||
new LabelledValue(
|
||||
globalType,
|
||||
labelledValues[i].label,
|
||||
labelledValues[i].value,
|
||||
widthPercent,
|
||||
@@ -55,19 +63,24 @@ export class LabelledValues extends Row {
|
||||
);
|
||||
}
|
||||
} else {
|
||||
this.elements.push(
|
||||
this.contextElements.push(
|
||||
new Column(
|
||||
globalType,
|
||||
0,
|
||||
0,
|
||||
labelledValues.map(
|
||||
(libelledValue) =>
|
||||
new LabelledValue(
|
||||
globalType,
|
||||
libelledValue.label,
|
||||
libelledValue.value,
|
||||
widthPercent,
|
||||
multiline
|
||||
)
|
||||
)
|
||||
),
|
||||
{
|
||||
name: `${this.context.name}-column`,
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -77,8 +90,8 @@ export class LabelledValues extends Row {
|
||||
public prepareRender(doc: jsPDF, maxWidth?: number): jsPDF {
|
||||
const pageWidth = doc.internal.pageSize.width;
|
||||
const rowWidth = pageWidth - this.x - MARGINS.right;
|
||||
for (const column of this.elements) {
|
||||
for (const labelledValue of (<Column>column).elements) {
|
||||
for (const column of this.pdfElements) {
|
||||
for (const labelledValue of (<Column>column).pdfElements) {
|
||||
labelledValue.maxWidth = rowWidth / this.nbrOfCol;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
import { AbstractElement } from './abstract-element';
|
||||
import jsPDF, { TextOptionsLight } from 'jspdf';
|
||||
import { i18nLocalize, TEXT_SIZE } from '../constants';
|
||||
import { HTML_TEXT_SIZE, i18nLocalize, TEXT_SIZE } from '../constants';
|
||||
import { Text } from './text';
|
||||
import { IContext } from './context';
|
||||
import { GenerateTypeEnum } from './generate-type.enum';
|
||||
|
||||
export class MultilineText extends Text {
|
||||
private nbrLine = 1;
|
||||
|
||||
constructor(
|
||||
globalType: GenerateTypeEnum,
|
||||
x: number,
|
||||
y: number,
|
||||
text: string,
|
||||
textOptions?: TextOptionsLight
|
||||
textOptions?: TextOptionsLight,
|
||||
context: Partial<IContext> = AbstractElement.DEFAULT_CONTEXT
|
||||
) {
|
||||
super(x, y, text, textOptions);
|
||||
super(globalType, x, y, text, textOptions, context);
|
||||
}
|
||||
|
||||
public prepareRender(doc: jsPDF, maxWidth?: number): jsPDF {
|
||||
@@ -32,6 +36,27 @@ export class MultilineText extends Text {
|
||||
return doc;
|
||||
}
|
||||
|
||||
public renderHtml(
|
||||
doc: Document,
|
||||
parent: HTMLElement,
|
||||
cssRules: string[],
|
||||
sheet: HTMLStyleElement
|
||||
): Document {
|
||||
const text = doc.createElement('p');
|
||||
const css = `text-${TEXT_SIZE}`;
|
||||
text.classList.add(`multiline-text`);
|
||||
text.classList.add(css);
|
||||
text.classList.add(this.context.name);
|
||||
if (!cssRules.includes(css)) {
|
||||
cssRules.push(css);
|
||||
sheet.innerHTML += ` .${css} { font-size: ${HTML_TEXT_SIZE}rem }`;
|
||||
sheet.innerHTML += ` .labelled-text > .${css} { font-size: ${HTML_TEXT_SIZE}rem; margin: 0; }`;
|
||||
}
|
||||
text.innerHTML = i18nLocalize(this.text);
|
||||
parent.append(text);
|
||||
return doc;
|
||||
}
|
||||
|
||||
public getHeight(doc): number {
|
||||
return this.getHeightFromPx(doc, TEXT_SIZE) * this.nbrLine;
|
||||
}
|
||||
|
||||
@@ -1,28 +1,31 @@
|
||||
import { AbstractElement } from './abstract-element';
|
||||
import jsPDF from 'jspdf';
|
||||
import { MARGINS } from '../constants';
|
||||
import { IContext } from './context';
|
||||
import { AbstractContainerElement } from './abstract-container-element';
|
||||
import { GenerateTypeEnum } from './generate-type.enum';
|
||||
|
||||
export class Row extends AbstractElement {
|
||||
public elements: AbstractElement[] = [];
|
||||
export class Row extends AbstractContainerElement {
|
||||
public widthPercents?: number[];
|
||||
public maxWidths?: number[];
|
||||
|
||||
constructor(
|
||||
globalType: GenerateTypeEnum,
|
||||
x: number,
|
||||
y: number,
|
||||
elements: AbstractElement[],
|
||||
maxWidth?: number | undefined,
|
||||
widthPercents?: number[],
|
||||
maxWidths?: number[]
|
||||
maxWidths?: number[],
|
||||
context: Partial<IContext> = AbstractElement.DEFAULT_CONTEXT
|
||||
) {
|
||||
super(x, y, maxWidth);
|
||||
this.elements = elements ?? [];
|
||||
super(globalType, x, y, maxWidth, elements, context);
|
||||
this.widthPercents = widthPercents ?? [];
|
||||
this.maxWidths = maxWidths ?? [];
|
||||
}
|
||||
|
||||
public prepareRender(doc: jsPDF, maxWidth?: number): jsPDF {
|
||||
const elements = this.elements ?? [];
|
||||
const elements = this.pdfElements ?? [];
|
||||
let maxWidths = this.maxWidths ?? [];
|
||||
let widthPercents = this.widthPercents ?? [];
|
||||
|
||||
@@ -60,9 +63,27 @@ export class Row extends AbstractElement {
|
||||
return doc;
|
||||
}
|
||||
|
||||
public renderHtml(
|
||||
doc: Document,
|
||||
parent: HTMLElement,
|
||||
cssRules: string[],
|
||||
sheet: HTMLStyleElement
|
||||
): Document {
|
||||
const div = doc.createElement('div');
|
||||
div.classList.add(`row`);
|
||||
div.classList.add(this.context.name);
|
||||
const elements = this.htmlElements ?? [];
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
const element = elements[i];
|
||||
element.renderHtml(doc, div, cssRules, sheet);
|
||||
}
|
||||
parent.append(div);
|
||||
return doc;
|
||||
}
|
||||
|
||||
public getHeight(doc?: jsPDF): number {
|
||||
let maxHeight = 0;
|
||||
for (const element of this.elements) {
|
||||
for (const element of this.pdfElements) {
|
||||
maxHeight = Math.max(maxHeight, element.getHeight(doc));
|
||||
}
|
||||
return maxHeight;
|
||||
@@ -70,21 +91,9 @@ export class Row extends AbstractElement {
|
||||
|
||||
public getCheckNewPageHeight(doc?: jsPDF): number {
|
||||
let maxHeight = 0;
|
||||
for (const element of this.elements) {
|
||||
for (const element of this.pdfElements) {
|
||||
maxHeight = Math.max(maxHeight, element.getCheckNewPageHeight(doc));
|
||||
}
|
||||
return maxHeight;
|
||||
}
|
||||
|
||||
public getElements(): AbstractElement[] {
|
||||
const elements: AbstractElement[] = [];
|
||||
for (const element of this.elements) {
|
||||
elements.push(...element.getElements());
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
public isEmpty(): boolean {
|
||||
return this.elements.length === 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
import { AbstractElement } from './abstract-element';
|
||||
import jsPDF from 'jspdf';
|
||||
import { MARGINS } from '../constants';
|
||||
import { IContext } from './context';
|
||||
import { GenerateTypeEnum } from './generate-type.enum';
|
||||
|
||||
export class Separator extends AbstractElement {
|
||||
constructor(x: number, y: number, maxWidth?: number | undefined) {
|
||||
super(x, y, maxWidth);
|
||||
constructor(
|
||||
globalType: GenerateTypeEnum,
|
||||
x: number,
|
||||
y: number,
|
||||
maxWidth?: number | undefined,
|
||||
context: Partial<IContext> = AbstractElement.DEFAULT_CONTEXT
|
||||
) {
|
||||
super(globalType, x, y, maxWidth, context);
|
||||
}
|
||||
|
||||
public getHeight(_doc?: jsPDF): number {
|
||||
@@ -33,6 +41,19 @@ export class Separator extends AbstractElement {
|
||||
return doc;
|
||||
}
|
||||
|
||||
public renderHtml(
|
||||
doc: Document,
|
||||
parent: HTMLElement,
|
||||
_cssRules: string[],
|
||||
_sheet: HTMLStyleElement
|
||||
): Document {
|
||||
const div = doc.createElement('div');
|
||||
div.classList.add(`separator`);
|
||||
div.classList.add(this.context.name);
|
||||
parent.append(div);
|
||||
return doc;
|
||||
}
|
||||
|
||||
public getElements(): AbstractElement[] {
|
||||
return [this];
|
||||
}
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
import { AbstractElement } from './abstract-element';
|
||||
import jsPDF, { TextOptionsLight } from 'jspdf';
|
||||
import { i18nLocalize, TEXT_SIZE } from '../constants';
|
||||
import { HTML_TEXT_SIZE, i18nLocalize, TEXT_SIZE } from '../constants';
|
||||
import { IContext } from './context';
|
||||
import { GenerateTypeEnum } from './generate-type.enum';
|
||||
|
||||
export class Text extends AbstractElement {
|
||||
public text: string;
|
||||
public textOptions?: TextOptionsLight;
|
||||
|
||||
constructor(
|
||||
globalType: GenerateTypeEnum,
|
||||
x: number,
|
||||
y: number,
|
||||
text: string,
|
||||
textOptions?: TextOptionsLight
|
||||
textOptions?: TextOptionsLight,
|
||||
context: Partial<IContext> = AbstractElement.DEFAULT_CONTEXT
|
||||
) {
|
||||
super(x, y, textOptions?.maxWidth);
|
||||
super(globalType, x, y, textOptions?.maxWidth, context);
|
||||
this.text = text;
|
||||
this.textOptions = textOptions;
|
||||
}
|
||||
@@ -36,6 +40,27 @@ export class Text extends AbstractElement {
|
||||
return doc;
|
||||
}
|
||||
|
||||
public renderHtml(
|
||||
doc: Document,
|
||||
parent: HTMLElement,
|
||||
cssRules: string[],
|
||||
sheet: HTMLStyleElement
|
||||
): Document {
|
||||
const text = doc.createElement('p');
|
||||
const css = `text-${TEXT_SIZE}`;
|
||||
text.classList.add(`ellipsis`);
|
||||
text.classList.add(css);
|
||||
text.classList.add(this.context.name);
|
||||
text.innerHTML = i18nLocalize(i18nLocalize(this.text));
|
||||
if (!cssRules.includes(css)) {
|
||||
cssRules.push(css);
|
||||
sheet.innerHTML += ` .${css} { font-size: ${HTML_TEXT_SIZE}rem }`;
|
||||
sheet.innerHTML += ` .labelled-text > .${css} { font-size: ${HTML_TEXT_SIZE}rem; margin: 0; }`;
|
||||
}
|
||||
parent.append(text);
|
||||
return doc;
|
||||
}
|
||||
|
||||
protected updateMaxWidth(maxWidth?: number) {
|
||||
if (maxWidth != null && maxWidth > 0) {
|
||||
this.maxWidth = maxWidth;
|
||||
|
||||
@@ -4,19 +4,24 @@ import jsPDF from 'jspdf';
|
||||
import { MARGINS } from '../constants';
|
||||
import { Text } from './text';
|
||||
import { MultilineText } from './multiline-text';
|
||||
import { IContext } from './context';
|
||||
import { AbstractElement } from './abstract-element';
|
||||
import { GenerateTypeEnum } from './generate-type.enum';
|
||||
|
||||
export class Texts extends Row {
|
||||
public texts: string[];
|
||||
public nbrOfCol: number;
|
||||
|
||||
constructor(
|
||||
globalType: GenerateTypeEnum,
|
||||
x: number,
|
||||
y: number,
|
||||
texts: string[],
|
||||
nbrOfCol?: number,
|
||||
multiline = false
|
||||
multiline = false,
|
||||
context: Partial<IContext> = AbstractElement.DEFAULT_CONTEXT
|
||||
) {
|
||||
super(x, y, []);
|
||||
super(globalType, x, y, [], undefined, undefined, undefined, context);
|
||||
this.texts = texts;
|
||||
this.nbrOfCol = nbrOfCol ?? 4;
|
||||
if (this.nbrOfCol > 4) {
|
||||
@@ -34,7 +39,7 @@ export class Texts extends Row {
|
||||
rest > 3 ? nbrPerCol + 1 : nbrPerCol,
|
||||
];
|
||||
for (let i = 0; i < this.nbrOfCol; i++) {
|
||||
this.elements[i] = new Column(0, 0, []);
|
||||
this.contextElements[i] = new Column(this.globalType, 0, 0, []);
|
||||
}
|
||||
for (let i = 0; i < texts.length; i++) {
|
||||
if (i < nbrPerCols[0]) {
|
||||
@@ -46,25 +51,26 @@ export class Texts extends Row {
|
||||
} else {
|
||||
currentIndex = 3;
|
||||
}
|
||||
(<Column>this.elements[currentIndex]).elements.push(
|
||||
new Row(0, 0, [
|
||||
(<Column>this.contextElements[currentIndex]).contextElements.push(
|
||||
new Row(this.globalType, 0, 0, [
|
||||
multiline
|
||||
? new MultilineText(0, 0, texts[i])
|
||||
: new Text(0, 0, texts[i]),
|
||||
? new MultilineText(this.globalType, 0, 0, texts[i])
|
||||
: new Text(this.globalType, 0, 0, texts[i]),
|
||||
])
|
||||
);
|
||||
}
|
||||
} else {
|
||||
this.elements.push(
|
||||
this.contextElements.push(
|
||||
new Column(
|
||||
this.globalType,
|
||||
0,
|
||||
0,
|
||||
texts.map(
|
||||
(text) =>
|
||||
new Row(0, 0, [
|
||||
new Row(this.globalType, 0, 0, [
|
||||
multiline
|
||||
? new MultilineText(0, 0, text)
|
||||
: new Text(0, 0, text),
|
||||
? new MultilineText(this.globalType, 0, 0, text)
|
||||
: new Text(this.globalType, 0, 0, text),
|
||||
])
|
||||
)
|
||||
)
|
||||
@@ -76,8 +82,8 @@ export class Texts extends Row {
|
||||
public prepareRender(doc: jsPDF, maxWidth?: number): jsPDF {
|
||||
const pageWidth = doc.internal.pageSize.width;
|
||||
const rowWidth = pageWidth - this.x - MARGINS.right;
|
||||
for (const column of this.elements) {
|
||||
for (const labelledValue of (<Column>column).elements) {
|
||||
for (const column of this.pdfElements) {
|
||||
for (const labelledValue of (<Column>column).pdfElements) {
|
||||
labelledValue.maxWidth = rowWidth / this.nbrOfCol;
|
||||
}
|
||||
}
|
||||
|
||||
94
src/html-builder.ts
Normal file
94
src/html-builder.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
741
src/main.ts
741
src/main.ts
File diff suppressed because it is too large
Load Diff
@@ -1,17 +1,29 @@
|
||||
import jsPDF, { jsPDFOptions } from 'jspdf';
|
||||
import { AbstractElement } from './elements/abstract-element';
|
||||
import { MARGINS } from './constants';
|
||||
import { LABEL_SIZE, MARGINS, TEXT_SIZE } from './constants';
|
||||
import { AbstractBuilder } from './abstract-builder';
|
||||
import { Util } from './util';
|
||||
import { GenerateTypeEnum } from './elements/generate-type.enum';
|
||||
|
||||
export class PdfBuilder {
|
||||
export class PdfBuilder extends AbstractBuilder {
|
||||
public doc: jsPDF;
|
||||
|
||||
constructor(options: jsPDFOptions) {
|
||||
super();
|
||||
this.doc = new jsPDF(options);
|
||||
}
|
||||
|
||||
public getLabelledRowHeight(): number {
|
||||
return Util.getHeightFromPx(this.doc, TEXT_SIZE + LABEL_SIZE) + 1;
|
||||
}
|
||||
|
||||
public save(name: string) {
|
||||
this.doc.save(`${name}.pdf`);
|
||||
}
|
||||
|
||||
public build(elements: AbstractElement[]) {
|
||||
const finalElements: AbstractElement[] = [];
|
||||
for (const element of elements) {
|
||||
for (const element of elements.filter((el) => el.context.isPdf)) {
|
||||
element.prepareRender(this.doc);
|
||||
finalElements.push(...element.getElements());
|
||||
}
|
||||
@@ -58,4 +70,12 @@ export class PdfBuilder {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public getImageScale(): number {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public getGenerateType(): GenerateTypeEnum {
|
||||
return GenerateTypeEnum.PDF;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user