@cenk1cenk2/md-printer 2.21.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +333 -48
- package/bin/dev.js +0 -2
- package/bin/run.js +0 -1
- package/dist/_virtual/_@oxc-project_runtime@0.153.0/helpers/esm/decorate.mjs +1 -2
- package/dist/_virtual/_@oxc-project_runtime@0.153.0/helpers/esm/decorateMetadata.mjs +1 -2
- package/dist/_virtual/_@oxc-project_runtime@0.153.0/helpers/esm/decorateParam.mjs +8 -0
- package/dist/commands/index.mjs +32 -345
- package/dist/components/Date.svelte +1 -0
- package/dist/components/Markdown.svelte +20 -0
- package/dist/components/Nodes.svelte +32 -0
- package/dist/components/Page.svelte +20 -0
- package/dist/components/PageBreak.svelte +5 -0
- package/dist/components/PageNumber.svelte +1 -0
- package/dist/components/SignatureBlock.svelte +56 -0
- package/dist/components/Title.svelte +1 -0
- package/dist/components/TotalPages.svelte +1 -0
- package/dist/components/index.ts +8 -0
- package/dist/constants/file.constants.mjs +1 -8
- package/dist/constants/index.mjs +5 -4
- package/dist/constants/preview.constants.mjs +9 -0
- package/dist/constants/signature.constants.mjs +7 -0
- package/dist/constants/template.constants.mjs +48 -10
- package/dist/interfaces/commands/index.mjs +1 -1
- package/dist/interfaces/commands/run.interface.mjs +1 -1
- package/dist/interfaces/index.mjs +1 -1
- package/dist/interfaces/markdown.interface.mjs +1 -0
- package/dist/interfaces/renderer.interface.mjs +1 -0
- package/dist/interfaces/session.interface.mjs +1 -0
- package/dist/interfaces/signature.interface.mjs +1 -1
- package/dist/interfaces/template.interface.mjs +1 -0
- package/dist/modules/md-printer/md-printer.handler.mjs +113 -0
- package/dist/modules/md-printer/md-printer.module.mjs +21 -0
- package/dist/modules/md-printer/md-printer.schema.mjs +50 -0
- package/dist/services/i18n.service.mjs +12 -15
- package/dist/services/index.mjs +9 -2
- package/dist/services/loopback.mjs +18 -0
- package/dist/services/markdown.service.mjs +123 -0
- package/dist/services/printer.module.mjs +39 -0
- package/dist/services/printer.service.mjs +171 -0
- package/dist/services/renderer/browser.mjs +41 -0
- package/dist/services/renderer/browser.service.mjs +56 -0
- package/dist/services/renderer/renderer.service.mjs +198 -0
- package/dist/services/session/Preview.svelte +238 -0
- package/dist/services/session/preview.service.mjs +187 -0
- package/dist/services/session/session.service.mjs +115 -0
- package/dist/services/signature/adapters/a-trust.adapter.mjs +32 -36
- package/dist/services/signature/index.mjs +1 -2
- package/dist/services/signature/signature.adapter.mjs +1 -2
- package/dist/services/signature/signature.service.mjs +6 -10
- package/dist/services/template/Document.svelte +21 -0
- package/dist/services/template/Margin.svelte +15 -0
- package/dist/services/template/assets.mjs +127 -0
- package/dist/services/template/render.entry.ts +32 -0
- package/dist/services/template/svelte.plugin.mjs +66 -0
- package/dist/services/template/template.service.mjs +211 -0
- package/oclif.manifest.json +49 -36
- package/package.json +69 -35
- package/templates/default/Template.svelte +83 -0
- package/templates/default/settings.json +1 -3
- package/templates/invoice/Template.svelte +247 -0
- package/templates/invoice/components/Client.svelte +42 -0
- package/templates/invoice/components/Company.svelte +41 -0
- package/templates/invoice/components/Items.svelte +66 -0
- package/templates/invoice/components/Notes.svelte +21 -0
- package/templates/invoice/components/Payment.svelte +25 -0
- package/templates/invoice/components/Signature.svelte +34 -0
- package/templates/invoice/components/Totals.svelte +47 -0
- package/templates/invoice/round.js +2 -0
- package/templates/invoice/settings.json +1 -4
- package/templates/kilic.dev/Template.svelte +102 -0
- package/templates/kilic.dev/settings.json +1 -3
- package/templates/mail/Template.svelte +166 -0
- package/templates/mail/settings.json +1 -3
- package/dist/hooks/not-found.hook.mjs +0 -7
- package/dist/hooks/update-notifier.hook.mjs +0 -7
- package/dist/interfaces/pupeteer.mjs +0 -1
- package/templates/default/main.css +0 -73
- package/templates/invoice/.gitignore +0 -1
- package/templates/invoice/footer.html +0 -18
- package/templates/invoice/tailwind.css +0 -164
- package/templates/invoice/template.html.j2 +0 -226
- package/templates/kilic.dev/footer.html +0 -26
- package/templates/kilic.dev/header.html +0 -16
- package/templates/kilic.dev/main.css +0 -74
- package/templates/mail/.gitignore +0 -1
- package/templates/mail/tailwind.css +0 -145
- package/templates/mail/template.html.j2 +0 -14
|
@@ -1,22 +1,60 @@
|
|
|
1
1
|
//#region src/constants/template.constants.ts
|
|
2
2
|
let TemplateFiles = /* @__PURE__ */ function(TemplateFiles) {
|
|
3
|
-
TemplateFiles["
|
|
4
|
-
TemplateFiles["HEADER"] = "header.html";
|
|
5
|
-
TemplateFiles["TEMPLATE"] = "template.html.j2";
|
|
6
|
-
TemplateFiles["TAILWIND_CSS"] = "tailwind.css";
|
|
7
|
-
TemplateFiles["CSS"] = "main.css";
|
|
3
|
+
TemplateFiles["TEMPLATE"] = "Template.svelte";
|
|
8
4
|
TemplateFiles["SETTINGS"] = "settings.json";
|
|
9
5
|
return TemplateFiles;
|
|
10
6
|
}({});
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
let RenderMode = /* @__PURE__ */ function(RenderMode) {
|
|
8
|
+
RenderMode["BODY"] = "body";
|
|
9
|
+
RenderMode["HEADER"] = "header";
|
|
10
|
+
RenderMode["FOOTER"] = "footer";
|
|
11
|
+
return RenderMode;
|
|
12
|
+
}({});
|
|
13
|
+
let MediaType = /* @__PURE__ */ function(MediaType) {
|
|
14
|
+
MediaType["SCREEN"] = "screen";
|
|
15
|
+
MediaType["PRINT"] = "print";
|
|
16
|
+
return MediaType;
|
|
17
|
+
}({});
|
|
18
|
+
let Directory = /* @__PURE__ */ function(Directory) {
|
|
19
|
+
Directory["TEMPLATES"] = "templates";
|
|
20
|
+
Directory["COMPONENTS"] = "components";
|
|
21
|
+
Directory["I18N"] = "i18n";
|
|
22
|
+
return Directory;
|
|
23
|
+
}({});
|
|
24
|
+
let ModuleSpecifier = /* @__PURE__ */ function(ModuleSpecifier) {
|
|
25
|
+
ModuleSpecifier["TEMPLATE"] = "md-printer:template";
|
|
26
|
+
ModuleSpecifier["COMPONENTS"] = "@cenk1cenk2/md-printer/components";
|
|
27
|
+
ModuleSpecifier["TEMPLATE_COMPONENTS"] = "md-printer:template-components";
|
|
28
|
+
return ModuleSpecifier;
|
|
29
|
+
}({});
|
|
30
|
+
let ContextKey = /* @__PURE__ */ function(ContextKey) {
|
|
31
|
+
ContextKey["RENDER_MODE"] = "md-printer:mode";
|
|
32
|
+
ContextKey["DOCUMENT"] = "md-printer:document";
|
|
33
|
+
ContextKey["MARKDOWN"] = "md-printer:markdown";
|
|
34
|
+
ContextKey["COMPONENTS"] = "md-printer:components";
|
|
35
|
+
return ContextKey;
|
|
36
|
+
}({});
|
|
37
|
+
const TAILWIND_STYLE_LANG = "postcss";
|
|
38
|
+
const PAGE_BREAK_CLASS = "page-break";
|
|
39
|
+
const DIRECTIVE_TAG = "md-printer-directive";
|
|
40
|
+
const PRINTER_MODULE_OPTIONS = Symbol("md-printer:options");
|
|
14
41
|
const I18N_ACCEPTED_TYPES = [
|
|
15
42
|
".yaml",
|
|
16
43
|
".yml",
|
|
17
44
|
".json"
|
|
18
45
|
];
|
|
19
46
|
const DEFAULT_LANGUAGE = "en";
|
|
20
|
-
|
|
47
|
+
const DEFAULT_TEMPLATE = "default";
|
|
48
|
+
const DEFAULT_HIGHLIGHT_STYLE = "atom-one-dark";
|
|
49
|
+
const DEFAULT_PDF_OPTIONS = {
|
|
50
|
+
format: "A4",
|
|
51
|
+
printBackground: true,
|
|
52
|
+
margin: {
|
|
53
|
+
top: "30mm",
|
|
54
|
+
right: "40mm",
|
|
55
|
+
bottom: "30mm",
|
|
56
|
+
left: "20mm"
|
|
57
|
+
}
|
|
58
|
+
};
|
|
21
59
|
//#endregion
|
|
22
|
-
export { DEFAULT_LANGUAGE, I18N_ACCEPTED_TYPES,
|
|
60
|
+
export { ContextKey, DEFAULT_HIGHLIGHT_STYLE, DEFAULT_LANGUAGE, DEFAULT_PDF_OPTIONS, DEFAULT_TEMPLATE, DIRECTIVE_TAG, Directory, I18N_ACCEPTED_TYPES, MediaType, ModuleSpecifier, PAGE_BREAK_CLASS, PRINTER_MODULE_OPTIONS, RenderMode, TAILWIND_STYLE_LANG, TemplateFiles };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.153.0/helpers/esm/decorateMetadata.mjs";
|
|
2
|
+
import __decorate from "../../_virtual/_@oxc-project_runtime@0.153.0/helpers/esm/decorate.mjs";
|
|
3
|
+
import { BrowserService } from "../../services/renderer/browser.service.mjs";
|
|
4
|
+
import { PrinterService } from "../../services/printer.service.mjs";
|
|
5
|
+
import { PreviewService } from "../../services/session/preview.service.mjs";
|
|
6
|
+
import { SessionService } from "../../services/session/session.service.mjs";
|
|
7
|
+
import "../../services/index.mjs";
|
|
8
|
+
import { Injectable } from "@nestjs/common";
|
|
9
|
+
import { mkdir } from "fs/promises";
|
|
10
|
+
import { dirname } from "path";
|
|
11
|
+
import { text } from "stream/consumers";
|
|
12
|
+
import writeFileAtomic from "write-file-atomic";
|
|
13
|
+
import { LoggerService } from "@cenk1cenk2/oclif-common";
|
|
14
|
+
//#region src/modules/md-printer/md-printer.handler.ts
|
|
15
|
+
let MdPrinterHandler = class MdPrinterHandler {
|
|
16
|
+
logger;
|
|
17
|
+
printer;
|
|
18
|
+
browser;
|
|
19
|
+
session;
|
|
20
|
+
preview;
|
|
21
|
+
constructor(logger, printer, browser, session, preview) {
|
|
22
|
+
this.logger = logger;
|
|
23
|
+
this.printer = printer;
|
|
24
|
+
this.browser = browser;
|
|
25
|
+
this.session = session;
|
|
26
|
+
this.preview = preview;
|
|
27
|
+
}
|
|
28
|
+
async run(context) {
|
|
29
|
+
const { flags, args } = context;
|
|
30
|
+
const options = {
|
|
31
|
+
...args.file !== void 0 ? { file: args.file } : { stdin: await text(process.stdin) },
|
|
32
|
+
output: args.output,
|
|
33
|
+
inputFiletype: flags["input-filetype"],
|
|
34
|
+
outputFiletype: flags["output-filetype"],
|
|
35
|
+
stdout: flags.stdout,
|
|
36
|
+
template: flags.template,
|
|
37
|
+
title: flags.title,
|
|
38
|
+
language: flags.language,
|
|
39
|
+
continuous: flags.continuous,
|
|
40
|
+
sign: flags.sign,
|
|
41
|
+
signProvider: flags["sign-provider"],
|
|
42
|
+
signCertificate: flags["sign-certificate"]
|
|
43
|
+
};
|
|
44
|
+
if (flags.preview) await this.watch(context, options);
|
|
45
|
+
else await this.print(options);
|
|
46
|
+
}
|
|
47
|
+
async print(flags) {
|
|
48
|
+
const input = await this.printer.input(flags);
|
|
49
|
+
const ctx = {
|
|
50
|
+
input,
|
|
51
|
+
options: await this.printer.options(flags, input)
|
|
52
|
+
};
|
|
53
|
+
this.logger.debug("Options: %o", ctx.options);
|
|
54
|
+
await this.printer.prepare(ctx);
|
|
55
|
+
const document = await this.printer.document(ctx, await this.printer.bundle(ctx.options));
|
|
56
|
+
let { content } = await this.printer.output(ctx, document);
|
|
57
|
+
if (ctx.signature) {
|
|
58
|
+
content = await this.printer.sign(ctx, content);
|
|
59
|
+
this.logger.info("Document is signed.");
|
|
60
|
+
}
|
|
61
|
+
await this.write(ctx, content, flags.stdout);
|
|
62
|
+
}
|
|
63
|
+
async watch({ flags, signal }, options) {
|
|
64
|
+
let writes = Promise.resolve();
|
|
65
|
+
this.session.on("building", () => this.preview.building());
|
|
66
|
+
this.session.on("failed", (err) => {
|
|
67
|
+
this.logger.error(err.message);
|
|
68
|
+
this.preview.failed(err);
|
|
69
|
+
});
|
|
70
|
+
this.session.on("ready", async (build) => {
|
|
71
|
+
this.preview.ready(build);
|
|
72
|
+
if (!build.ctx.options.dest) {
|
|
73
|
+
this.logger.info("Rebuilt in %dms.", build.ms);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
this.session.ignore(build.ctx.options.dest);
|
|
77
|
+
writes = writes.then(() => this.write(build.ctx, build.output, options.stdout)).catch((err) => this.logger.error(err.message));
|
|
78
|
+
await writes;
|
|
79
|
+
});
|
|
80
|
+
if (options.sign) this.logger.warn("Signing is skipped while previewing, run without --preview to sign the document.");
|
|
81
|
+
const stopped = new Promise((resolve) => signal.addEventListener("abort", () => resolve(), { once: true }));
|
|
82
|
+
await this.session.start(options);
|
|
83
|
+
const url = await this.preview.listen({
|
|
84
|
+
host: flags.host,
|
|
85
|
+
port: flags.port
|
|
86
|
+
});
|
|
87
|
+
this.logger.info("Preview is running at %s, press Ctrl+C to stop.", url);
|
|
88
|
+
await Promise.race([stopped, flags.open ? this.preview.open(this.browser.executable(), url) : new Promise(() => void 0)]);
|
|
89
|
+
await this.preview.close();
|
|
90
|
+
await this.session.stop();
|
|
91
|
+
await writes;
|
|
92
|
+
}
|
|
93
|
+
async write(ctx, content, stdout) {
|
|
94
|
+
const { dest } = ctx.options;
|
|
95
|
+
if (!dest) {
|
|
96
|
+
if (!stdout) throw new Error("No output file to write, pass an output argument, set dest in front-matter or use --stdout.");
|
|
97
|
+
process.stdout.write(content);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
await mkdir(dirname(dest), { recursive: true });
|
|
101
|
+
await writeFileAtomic(dest, content);
|
|
102
|
+
this.logger.info("Written: %s", dest);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
MdPrinterHandler = __decorate([Injectable(), __decorateMetadata("design:paramtypes", [
|
|
106
|
+
typeof LoggerService === "undefined" ? Object : LoggerService,
|
|
107
|
+
typeof PrinterService === "undefined" ? Object : PrinterService,
|
|
108
|
+
typeof BrowserService === "undefined" ? Object : BrowserService,
|
|
109
|
+
typeof SessionService === "undefined" ? Object : SessionService,
|
|
110
|
+
typeof PreviewService === "undefined" ? Object : PreviewService
|
|
111
|
+
])], MdPrinterHandler);
|
|
112
|
+
//#endregion
|
|
113
|
+
export { MdPrinterHandler };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import __decorate from "../../_virtual/_@oxc-project_runtime@0.153.0/helpers/esm/decorate.mjs";
|
|
2
|
+
import { PrinterModule } from "../../services/printer.module.mjs";
|
|
3
|
+
import "../../services/index.mjs";
|
|
4
|
+
import { MdPrinterHandler } from "./md-printer.handler.mjs";
|
|
5
|
+
import { Module } from "@nestjs/common";
|
|
6
|
+
import { CommandContext, LogLevels, LoggerModule, LogoModule } from "@cenk1cenk2/oclif-common";
|
|
7
|
+
//#region src/modules/md-printer/md-printer.module.ts
|
|
8
|
+
let MdPrinterModule = class MdPrinterModule {};
|
|
9
|
+
MdPrinterModule = __decorate([Module({
|
|
10
|
+
imports: [
|
|
11
|
+
LoggerModule.forRoot({ stderr: Object.values(LogLevels) }),
|
|
12
|
+
LogoModule.forRoot(),
|
|
13
|
+
PrinterModule.forRootAsync({
|
|
14
|
+
inject: [CommandContext],
|
|
15
|
+
useFactory: ({ flags }) => ({ browser: flags.browser })
|
|
16
|
+
})
|
|
17
|
+
],
|
|
18
|
+
providers: [MdPrinterHandler]
|
|
19
|
+
})], MdPrinterModule);
|
|
20
|
+
//#endregion
|
|
21
|
+
export { MdPrinterModule };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { InputFileType, OutputFileType } from "../../constants/file.constants.mjs";
|
|
2
|
+
import { PreviewHost } from "../../constants/preview.constants.mjs";
|
|
3
|
+
import { SignatureProvider } from "../../constants/signature.constants.mjs";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
//#region src/modules/md-printer/md-printer.schema.ts
|
|
6
|
+
const MdPrinterSchema = z.object({
|
|
7
|
+
flags: z.object({
|
|
8
|
+
stdin: z.boolean().default(false).describe("Read the input from stdin."),
|
|
9
|
+
["input-filetype"]: z.enum(InputFileType).optional().describe("Input file type. Detected from the file extension, markdown for stdin and unknown extensions."),
|
|
10
|
+
["output-filetype"]: z.enum(OutputFileType).optional().describe("Output file type, defaults to pdf. Overwrites the one defined in front-matter."),
|
|
11
|
+
stdout: z.boolean().default(false).describe("Write the output to stdout instead of a file."),
|
|
12
|
+
template: z.string().optional().describe("Built-in template name or path to a template directory, defaults to \"default\". Overwrites the one defined in front-matter."),
|
|
13
|
+
title: z.string().optional().describe("Document title. Overwrites the one defined in front-matter or the template."),
|
|
14
|
+
language: z.string().optional().describe("Language for template translations. Overwrites the one defined in front-matter and template settings."),
|
|
15
|
+
browser: z.string().optional().describe("Browser executable used for printing. Discovered automatically when omitted (Brave, Chrome, Chromium, Edge)."),
|
|
16
|
+
continuous: z.boolean().default(false).describe("Render the PDF as a single continuous page without page breaks."),
|
|
17
|
+
preview: z.boolean().default(false).describe("Rebuild whenever the input, the template or its assets change, show the HTML and the PDF in a live preview and rewrite the output file when there is one."),
|
|
18
|
+
host: z.enum(PreviewHost).default("127.0.0.1").describe("Loopback host for the preview server, it serves the files next to the input and is never exposed to the network."),
|
|
19
|
+
port: z.number().int().min(0).max(65535).default(0).describe("Port for the preview server, random when 0."),
|
|
20
|
+
open: z.boolean().default(true).describe("Open the preview window, --no-open keeps rebuilding and writing without one."),
|
|
21
|
+
sign: z.boolean().default(false).describe("Sign the PDF with a qualified electronic signature through ID Austria (A-Trust)."),
|
|
22
|
+
["sign-provider"]: z.enum(SignatureProvider).optional().describe("Signature provider, defaults to a-trust. Overwrites the one defined in front-matter and template settings."),
|
|
23
|
+
["sign-certificate"]: z.string().optional().describe("Signer certificate (DER or PEM) used for the visible signature block and to verify the returned signature.")
|
|
24
|
+
}),
|
|
25
|
+
args: z.object({
|
|
26
|
+
file: z.string().optional().describe("Markdown or yaml file to render."),
|
|
27
|
+
output: z.string().optional().describe("Output file. Overwrites the one defined in front-matter.")
|
|
28
|
+
})
|
|
29
|
+
}).superRefine(({ flags, args }, ctx) => {
|
|
30
|
+
if (!flags.stdin && !args.file) ctx.addIssue({
|
|
31
|
+
code: "custom",
|
|
32
|
+
message: "Either --stdin or file argument must be provided."
|
|
33
|
+
});
|
|
34
|
+
if (flags.stdin && args.output) ctx.addIssue({
|
|
35
|
+
code: "custom",
|
|
36
|
+
message: "Reading from --stdin takes only the output file argument."
|
|
37
|
+
});
|
|
38
|
+
if (flags.stdout && flags.preview) ctx.addIssue({
|
|
39
|
+
code: "custom",
|
|
40
|
+
message: "Writing to stdout is not supported with --preview."
|
|
41
|
+
});
|
|
42
|
+
}).transform(({ flags, args }) => ({
|
|
43
|
+
flags,
|
|
44
|
+
args: flags.stdin ? {
|
|
45
|
+
file: void 0,
|
|
46
|
+
output: args.file
|
|
47
|
+
} : args
|
|
48
|
+
}));
|
|
49
|
+
//#endregion
|
|
50
|
+
export { MdPrinterSchema };
|
|
@@ -1,40 +1,37 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { I18N_ACCEPTED_TYPES } from "../constants/template.constants.mjs";
|
|
2
2
|
import __decorateMetadata from "../_virtual/_@oxc-project_runtime@0.153.0/helpers/esm/decorateMetadata.mjs";
|
|
3
3
|
import __decorate from "../_virtual/_@oxc-project_runtime@0.153.0/helpers/esm/decorate.mjs";
|
|
4
|
-
import { basename, extname, join } from "path";
|
|
5
|
-
import { ConfigService, FileSystemService } from "@cenk1cenk2/oclif-common";
|
|
6
4
|
import { Injectable } from "@nestjs/common";
|
|
5
|
+
import { readdir } from "fs/promises";
|
|
6
|
+
import { basename, extname, join } from "path";
|
|
7
|
+
import { FileSystemService, ParserService } from "@cenk1cenk2/oclif-common";
|
|
7
8
|
import i18next from "i18next";
|
|
8
|
-
|
|
9
9
|
//#region src/services/i18n.service.ts
|
|
10
10
|
let I18nService = class I18nService {
|
|
11
11
|
fs;
|
|
12
|
-
|
|
13
|
-
constructor(fs,
|
|
12
|
+
parser;
|
|
13
|
+
constructor(fs, parser) {
|
|
14
14
|
this.fs = fs;
|
|
15
|
-
this.
|
|
15
|
+
this.parser = parser;
|
|
16
16
|
}
|
|
17
17
|
async load(directory, options) {
|
|
18
|
-
if (!this.fs.exists(directory)) return;
|
|
19
18
|
const instance = i18next.createInstance();
|
|
20
19
|
await instance.init({
|
|
21
20
|
lng: options.language,
|
|
22
21
|
fallbackLng: options.fallback ?? options.language ?? "en",
|
|
23
|
-
resources: await this.resources(directory),
|
|
22
|
+
resources: this.fs.exists(directory) ? await this.resources(directory) : {},
|
|
24
23
|
interpolation: { escapeValue: false }
|
|
25
24
|
});
|
|
26
25
|
return instance.getFixedT(options.language);
|
|
27
26
|
}
|
|
28
27
|
async resources(directory) {
|
|
29
|
-
const files = (await this.fs.extra.readdir(directory)).filter((file) => I18N_ACCEPTED_TYPES.includes(extname(file)));
|
|
30
28
|
const resources = {};
|
|
31
|
-
await Promise.all(
|
|
32
|
-
resources[basename(file, extname(file))] = { translation: await this.
|
|
29
|
+
await Promise.all((await readdir(directory)).filter((file) => I18N_ACCEPTED_TYPES.includes(extname(file))).map(async (file) => {
|
|
30
|
+
resources[basename(file, extname(file))] = { translation: await this.parser.read(join(directory, file)) };
|
|
33
31
|
}));
|
|
34
32
|
return resources;
|
|
35
33
|
}
|
|
36
34
|
};
|
|
37
|
-
I18nService = __decorate([Injectable(), __decorateMetadata("design:paramtypes", [typeof FileSystemService === "undefined" ? Object : FileSystemService, typeof
|
|
38
|
-
|
|
35
|
+
I18nService = __decorate([Injectable(), __decorateMetadata("design:paramtypes", [typeof FileSystemService === "undefined" ? Object : FileSystemService, typeof ParserService === "undefined" ? Object : ParserService])], I18nService);
|
|
39
36
|
//#endregion
|
|
40
|
-
export { I18nService };
|
|
37
|
+
export { I18nService };
|
package/dist/services/index.mjs
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { I18nService } from "./i18n.service.mjs";
|
|
2
|
+
import { MarkdownService } from "./markdown.service.mjs";
|
|
3
|
+
import { BrowserService } from "./renderer/browser.service.mjs";
|
|
4
|
+
import { RendererService } from "./renderer/renderer.service.mjs";
|
|
2
5
|
import { SignatureAdapter } from "./signature/signature.adapter.mjs";
|
|
3
6
|
import { ATrustAdapter } from "./signature/adapters/a-trust.adapter.mjs";
|
|
4
7
|
import { SignatureService } from "./signature/signature.service.mjs";
|
|
8
|
+
import { TemplateService } from "./template/template.service.mjs";
|
|
9
|
+
import { PrinterService } from "./printer.service.mjs";
|
|
10
|
+
import { PreviewService } from "./session/preview.service.mjs";
|
|
11
|
+
import { SessionService } from "./session/session.service.mjs";
|
|
12
|
+
import { PrinterModule } from "./printer.module.mjs";
|
|
5
13
|
import "./signature/index.mjs";
|
|
6
|
-
|
|
7
|
-
export { ATrustAdapter, I18nService, SignatureAdapter, SignatureService };
|
|
14
|
+
export { ATrustAdapter, BrowserService, I18nService, MarkdownService, PreviewService, PrinterModule, PrinterService, RendererService, SessionService, SignatureAdapter, SignatureService, TemplateService };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/services/loopback.ts
|
|
2
|
+
const LOOPBACK = [
|
|
3
|
+
"localhost",
|
|
4
|
+
"127.0.0.1",
|
|
5
|
+
"[::1]"
|
|
6
|
+
];
|
|
7
|
+
/**
|
|
8
|
+
* Accepts only requests addressed to a loopback host and, when a page sent them, coming from one: another site can then reach the local
|
|
9
|
+
* servers neither through DNS rebinding nor through a cross-site form post. With an expected `origin`, the request must come from exactly
|
|
10
|
+
* that origin, which also shuts out other local servers.
|
|
11
|
+
*/
|
|
12
|
+
function isLoopbackRequest({ headers }, origin) {
|
|
13
|
+
if (!LOOPBACK.includes(URL.parse(`http://${headers.host}`)?.hostname)) return false;
|
|
14
|
+
if (origin) return headers.origin === origin;
|
|
15
|
+
return !headers.origin || LOOPBACK.includes(URL.parse(headers.origin)?.hostname);
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { isLoopbackRequest };
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { DIRECTIVE_TAG, PAGE_BREAK_CLASS } from "../constants/template.constants.mjs";
|
|
2
|
+
import __decorate from "../_virtual/_@oxc-project_runtime@0.153.0/helpers/esm/decorate.mjs";
|
|
3
|
+
import { Injectable } from "@nestjs/common";
|
|
4
|
+
import { toHtml } from "hast-util-to-html";
|
|
5
|
+
import { all } from "lowlight";
|
|
6
|
+
import { find, html } from "property-information";
|
|
7
|
+
import rehypeHighlight from "rehype-highlight";
|
|
8
|
+
import rehypeRaw from "rehype-raw";
|
|
9
|
+
import rehypeSlug from "rehype-slug";
|
|
10
|
+
import remarkDirective from "remark-directive";
|
|
11
|
+
import remarkFrontmatter from "remark-frontmatter";
|
|
12
|
+
import remarkGfm from "remark-gfm";
|
|
13
|
+
import remarkParse from "remark-parse";
|
|
14
|
+
import remarkRehype from "remark-rehype";
|
|
15
|
+
import { unified } from "unified";
|
|
16
|
+
import { EXIT, SKIP, visit } from "unist-util-visit";
|
|
17
|
+
import { VFile } from "vfile";
|
|
18
|
+
import { matter } from "vfile-matter";
|
|
19
|
+
//#region src/services/markdown.service.ts
|
|
20
|
+
let MarkdownService = class MarkdownService {
|
|
21
|
+
processor = unified().use(remarkParse).use(remarkFrontmatter).use(remarkGfm).use(remarkDirective).use(() => (tree, file) => {
|
|
22
|
+
visit(tree, [
|
|
23
|
+
"containerDirective",
|
|
24
|
+
"leafDirective",
|
|
25
|
+
"textDirective"
|
|
26
|
+
], (node) => {
|
|
27
|
+
if (node.type === "leafDirective" && node.name === "pagebreak") {
|
|
28
|
+
node.data = {
|
|
29
|
+
hName: "div",
|
|
30
|
+
hProperties: { className: [PAGE_BREAK_CLASS] }
|
|
31
|
+
};
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
node.data = {
|
|
35
|
+
hName: DIRECTIVE_TAG,
|
|
36
|
+
hProperties: {
|
|
37
|
+
dataType: node.type,
|
|
38
|
+
dataName: node.name,
|
|
39
|
+
dataAttributes: JSON.stringify(Object.fromEntries(Object.entries(node.attributes ?? {}).map(([key, value]) => [key, value ?? ""]))),
|
|
40
|
+
dataSource: String(file.value).slice(node.position.start.offset, node.position.end.offset)
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
}).use(remarkRehype, { allowDangerousHtml: true }).use(rehypeRaw).use(rehypeHighlight, { languages: all }).freeze();
|
|
45
|
+
parse(source) {
|
|
46
|
+
const file = new VFile(source);
|
|
47
|
+
matter(file);
|
|
48
|
+
return {
|
|
49
|
+
markdown: this.processor.runSync(this.processor.parse(file), file),
|
|
50
|
+
data: file.data.matter ?? {}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Splits the document into HTML and the elements on the way to a component, so only directives render as components.
|
|
55
|
+
*/
|
|
56
|
+
resolve(tree, directives) {
|
|
57
|
+
const resolved = unified().use(() => (root) => {
|
|
58
|
+
visit(root, {
|
|
59
|
+
type: "element",
|
|
60
|
+
tagName: DIRECTIVE_TAG
|
|
61
|
+
}, (node, index, parent) => {
|
|
62
|
+
if (directives.has(String(node.properties.dataName))) return;
|
|
63
|
+
const text = {
|
|
64
|
+
type: "text",
|
|
65
|
+
value: String(node.properties.dataSource)
|
|
66
|
+
};
|
|
67
|
+
parent.children[index] = node.properties.dataType === "textDirective" ? text : {
|
|
68
|
+
type: "element",
|
|
69
|
+
tagName: "p",
|
|
70
|
+
properties: {},
|
|
71
|
+
children: [text]
|
|
72
|
+
};
|
|
73
|
+
return SKIP;
|
|
74
|
+
});
|
|
75
|
+
}).use(rehypeSlug).runSync(structuredClone(tree));
|
|
76
|
+
return this.nodes(resolved.children, directives);
|
|
77
|
+
}
|
|
78
|
+
nodes(children, directives) {
|
|
79
|
+
return children.reduce((nodes, child) => {
|
|
80
|
+
const node = this.node(child, directives);
|
|
81
|
+
const last = nodes.at(-1);
|
|
82
|
+
if (node.type === "html" && last?.type === "html") last.html += node.html;
|
|
83
|
+
else nodes.push(node);
|
|
84
|
+
return nodes;
|
|
85
|
+
}, []);
|
|
86
|
+
}
|
|
87
|
+
node(child, directives) {
|
|
88
|
+
let directive = false;
|
|
89
|
+
visit(child, {
|
|
90
|
+
type: "element",
|
|
91
|
+
tagName: DIRECTIVE_TAG
|
|
92
|
+
}, () => {
|
|
93
|
+
directive = true;
|
|
94
|
+
return EXIT;
|
|
95
|
+
});
|
|
96
|
+
if (child.type !== "element" || !directive) return {
|
|
97
|
+
type: "html",
|
|
98
|
+
html: toHtml(child)
|
|
99
|
+
};
|
|
100
|
+
if (child.tagName === "md-printer-directive") return {
|
|
101
|
+
type: "component",
|
|
102
|
+
name: directives.get(String(child.properties.dataName)),
|
|
103
|
+
props: JSON.parse(String(child.properties.dataAttributes)),
|
|
104
|
+
children: this.nodes(child.children, directives)
|
|
105
|
+
};
|
|
106
|
+
return {
|
|
107
|
+
type: "element",
|
|
108
|
+
tag: child.tagName,
|
|
109
|
+
attributes: this.attributes(child.properties),
|
|
110
|
+
children: this.nodes(child.children, directives)
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
attributes(properties) {
|
|
114
|
+
return Object.fromEntries(Object.entries(properties).flatMap(([key, value]) => {
|
|
115
|
+
if (value === null || value === void 0 || value === false) return [];
|
|
116
|
+
const { attribute, commaSeparated } = find(html, key);
|
|
117
|
+
return [[attribute, value === true ? true : Array.isArray(value) ? value.join(commaSeparated ? ", " : " ") : String(value)]];
|
|
118
|
+
}));
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
MarkdownService = __decorate([Injectable()], MarkdownService);
|
|
122
|
+
//#endregion
|
|
123
|
+
export { MarkdownService };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { PRINTER_MODULE_OPTIONS } from "../constants/template.constants.mjs";
|
|
2
|
+
import __decorate from "../_virtual/_@oxc-project_runtime@0.153.0/helpers/esm/decorate.mjs";
|
|
3
|
+
import { I18nService } from "./i18n.service.mjs";
|
|
4
|
+
import { MarkdownService } from "./markdown.service.mjs";
|
|
5
|
+
import { BrowserService } from "./renderer/browser.service.mjs";
|
|
6
|
+
import { RendererService } from "./renderer/renderer.service.mjs";
|
|
7
|
+
import { ATrustAdapter } from "./signature/adapters/a-trust.adapter.mjs";
|
|
8
|
+
import { SignatureService } from "./signature/signature.service.mjs";
|
|
9
|
+
import { TemplateService } from "./template/template.service.mjs";
|
|
10
|
+
import { PrinterService } from "./printer.service.mjs";
|
|
11
|
+
import { PreviewService } from "./session/preview.service.mjs";
|
|
12
|
+
import { SessionService } from "./session/session.service.mjs";
|
|
13
|
+
import { ConfigurableModuleBuilder, Module } from "@nestjs/common";
|
|
14
|
+
import { FilesystemModule, JsonParser, ParserModule, YamlParser } from "@cenk1cenk2/oclif-common";
|
|
15
|
+
//#region src/services/printer.module.ts
|
|
16
|
+
let PrinterModule = class PrinterModule extends new ConfigurableModuleBuilder({ optionsInjectionToken: PRINTER_MODULE_OPTIONS }).setClassMethodName("forRoot").build().ConfigurableModuleClass {};
|
|
17
|
+
PrinterModule = __decorate([Module({
|
|
18
|
+
imports: [FilesystemModule.forRoot(), ParserModule.forRoot({ parsers: [JsonParser, YamlParser] })],
|
|
19
|
+
providers: [
|
|
20
|
+
I18nService,
|
|
21
|
+
MarkdownService,
|
|
22
|
+
TemplateService,
|
|
23
|
+
BrowserService,
|
|
24
|
+
RendererService,
|
|
25
|
+
ATrustAdapter,
|
|
26
|
+
SignatureService,
|
|
27
|
+
PrinterService,
|
|
28
|
+
SessionService,
|
|
29
|
+
PreviewService
|
|
30
|
+
],
|
|
31
|
+
exports: [
|
|
32
|
+
PrinterService,
|
|
33
|
+
BrowserService,
|
|
34
|
+
SessionService,
|
|
35
|
+
PreviewService
|
|
36
|
+
]
|
|
37
|
+
})], PrinterModule);
|
|
38
|
+
//#endregion
|
|
39
|
+
export { PrinterModule };
|