@cenk1cenk2/md-printer 3.2.24 → 3.4.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 +213 -57
- package/dist/_virtual/{_@oxc-project_runtime@0.156.0 → _@oxc-project_runtime@0.157.0}/helpers/esm/decorate.mjs +1 -1
- package/dist/_virtual/{_@oxc-project_runtime@0.156.0 → _@oxc-project_runtime@0.157.0}/helpers/esm/decorateMetadata.mjs +1 -1
- package/dist/_virtual/{_@oxc-project_runtime@0.156.0 → _@oxc-project_runtime@0.157.0}/helpers/esm/decorateParam.mjs +1 -1
- package/dist/commands/index.mjs +3 -1
- package/dist/components/Localized.svelte +18 -0
- package/dist/components/SignatureBlock.svelte +8 -46
- package/dist/components/Translate.svelte +15 -0
- package/dist/components/extension.ts +8 -0
- package/dist/components/index.ts +3 -0
- package/dist/constants/attachment.constants.mjs +7 -0
- package/dist/constants/index.mjs +3 -2
- package/dist/constants/template.constants.mjs +26 -2
- package/dist/interfaces/attachment.interface.mjs +1 -0
- package/dist/modules/md-printer/md-printer.handler.mjs +4 -2
- package/dist/modules/md-printer/md-printer.module.mjs +1 -1
- package/dist/modules/md-printer/md-printer.schema.mjs +12 -1
- package/dist/services/i18n.service.mjs +6 -4
- package/dist/services/index.mjs +2 -1
- package/dist/services/markdown.service.mjs +1 -1
- package/dist/services/pdf/pdf.service.mjs +124 -0
- package/dist/services/printer.module.mjs +3 -1
- package/dist/services/printer.service.mjs +55 -11
- package/dist/services/renderer/browser.service.mjs +3 -3
- package/dist/services/renderer/renderer.service.mjs +3 -3
- package/dist/services/session/preview.service.mjs +2 -2
- package/dist/services/session/session.service.mjs +11 -11
- package/dist/services/signature/adapters/a-trust.adapter.mjs +2 -2
- package/dist/services/signature/signature.service.mjs +2 -2
- package/dist/services/template/assets.mjs +1 -1
- package/dist/services/template/render.entry.ts +6 -2
- package/dist/services/template/svelte.plugin.mjs +12 -7
- package/dist/services/template/template.schema.mjs +27 -0
- package/dist/services/template/template.service.mjs +123 -26
- package/oclif.manifest.json +16 -2
- package/package.json +14 -24
- package/templates/default/Template.svelte +0 -83
- package/templates/default/settings.json +0 -7
- package/templates/invoice/Template.svelte +0 -247
- package/templates/invoice/components/Client.svelte +0 -42
- package/templates/invoice/components/Company.svelte +0 -41
- package/templates/invoice/components/Items.svelte +0 -66
- package/templates/invoice/components/Notes.svelte +0 -21
- package/templates/invoice/components/Payment.svelte +0 -25
- package/templates/invoice/components/Signature.svelte +0 -34
- package/templates/invoice/components/Totals.svelte +0 -47
- package/templates/invoice/i18n/de.yaml +0 -30
- package/templates/invoice/i18n/en.yaml +0 -30
- package/templates/invoice/round.js +0 -2
- package/templates/invoice/settings.json +0 -11
- package/templates/kilic.dev/Template.svelte +0 -102
- package/templates/kilic.dev/settings.json +0 -7
- package/templates/mail/Template.svelte +0 -166
- package/templates/mail/settings.json +0 -7
package/README.md
CHANGED
|
@@ -92,7 +92,7 @@ Markdown files take YAML front-matter. For YAML input the same keys are top-leve
|
|
|
92
92
|
|
|
93
93
|
| Key | Description |
|
|
94
94
|
| ----------------- | --------------------------------------------------------------------------------------------- |
|
|
95
|
-
| `template` | Built-in template name
|
|
95
|
+
| `template` | Built-in template name, path to a template directory or an object, see [Template sources](#template-sources). |
|
|
96
96
|
| `dest` | Output file, relative to the current directory, not to the input file. |
|
|
97
97
|
| `outputFiletype` | `pdf` (default) or `html`. |
|
|
98
98
|
| `language` | Language for template translations. |
|
|
@@ -100,6 +100,8 @@ Markdown files take YAML front-matter. For YAML input the same keys are top-leve
|
|
|
100
100
|
| `documentTitle` | Document title. |
|
|
101
101
|
| `pdfOptions` | Puppeteer [PDF options](https://pptr.dev/api/puppeteer.pdfoptions), merged over the defaults. |
|
|
102
102
|
| `sign` | Signing options, see [Signing](#signing). |
|
|
103
|
+
| `attachments` | PDFs merged into the output, see [Attachments and compression](#attachments-and-compression). |
|
|
104
|
+
| `compress` | `true` compresses the images of the whole output PDF, attachments included. |
|
|
103
105
|
|
|
104
106
|
A template may carry a `settings.json` with defaults for its documents:
|
|
105
107
|
|
|
@@ -133,6 +135,29 @@ pdfOptions:
|
|
|
133
135
|
- `continuous` is enabled when any of `--continuous`, front-matter or `settings.json` enables it.
|
|
134
136
|
- The document title is `--title`, then `documentTitle`, then the `<title>` set by the template, then the input file name.
|
|
135
137
|
|
|
138
|
+
## Attachments and compression
|
|
139
|
+
|
|
140
|
+
PDF output can carry other PDFs, such as certificates or reference letters, and can be compressed.
|
|
141
|
+
|
|
142
|
+
```yaml
|
|
143
|
+
---
|
|
144
|
+
compress: true
|
|
145
|
+
attachments:
|
|
146
|
+
- file: ./assets/references/diploma.pdf
|
|
147
|
+
position: before
|
|
148
|
+
- file: https://example.com/certificate.pdf
|
|
149
|
+
position: 2
|
|
150
|
+
compress: true
|
|
151
|
+
- file: ./assets/references/letter.pdf
|
|
152
|
+
---
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
- `file` is a path relative to the input file, confined to its directory like every other local asset, or an `http(s)` URL.
|
|
156
|
+
- `position` is `before` the document, `after` it (the default) or a page number: the attachment starts at that page of the rendered document, so `2` places it between the first and the second page, and the page after the last one appends it. Page numbers always count pages of the rendered document, not of other attachments, and attachments sharing a position keep the order they are listed in.
|
|
157
|
+
- `compress: true` on an attachment re-encodes its images, `compress: true` at the top level does the same for the whole output, attachments included. Images are scaled down to at most 2000px and stored as JPEG at quality 75 whenever that makes them smaller; masks and images with transparency keep their lossless encoding.
|
|
158
|
+
- Attachments and compression are applied before signing, so a signature covers them. They are only supported for PDF output.
|
|
159
|
+
- `--preview` rebuilds when a local attachment changes.
|
|
160
|
+
|
|
136
161
|
## Development
|
|
137
162
|
|
|
138
163
|
```sh
|
|
@@ -152,25 +177,93 @@ md-printer document.md out.pdf --preview --no-open
|
|
|
152
177
|
|
|
153
178
|
### Built-in templates
|
|
154
179
|
|
|
180
|
+
Every built-in template is a package of its own, `@cenk1cenk2/md-printer-template-<name>`. md-printer depends on all of them, so they install with it, and each one brings the fonts, icons and stylesheets it uses as its own dependencies. `default`, `kilic.dev` and `mail` are published from the `templates/` directory of this repository, `cv` from https://gitlab.kilic.dev/cenk/cv and `invoice` from https://gitlab.kilic.dev/cenk/invoices.
|
|
181
|
+
|
|
155
182
|
| Name | Description |
|
|
156
183
|
| ----------- | -------------------------------------------------------------------------------------------------------------- |
|
|
157
184
|
| `default` | GitHub-flavoured Markdown styling with Montserrat. This is the default. |
|
|
158
185
|
| `kilic.dev` | Same styling with a logo in the header and a footer with title and page numbers. |
|
|
159
186
|
| `invoice` | Invoice from YAML data (`company`, `client`, `payment`, `items`, `currency`, `date`, `id`) and Markdown notes. Translations in `en` and `de`, a signature block when signing. See `test/invoice.md`. |
|
|
187
|
+
| `cv` | CV in the table layout of a classic Word CV, from front-matter (`name`, `suffix`, `title`, `tagline`, `photo`) and Markdown sections placed with the `::section`, `:::details` / `::detail` / `:::pair`, `:::entry`, `::::group` / `:::course`, `::skill`, `:::note` and `:::languages` / `::language` components. The PDF is tagged and has an outline, so screening tools read it as text. See `test/cv.md`. |
|
|
160
188
|
| `mail` | Plain content with no margin and Tailwind typography, meant for HTML output. |
|
|
161
189
|
|
|
190
|
+
### Template sources
|
|
191
|
+
|
|
192
|
+
`-t` and a string `template` in front-matter take a built-in name or a path. A value without a path separator is a built-in name, anything with `/` or starting with `.` or `~` is a path, relative to the current directory.
|
|
193
|
+
|
|
194
|
+
`template` in front-matter can also be an object selecting the source by `type`. This is the only way to use a template from an npm package.
|
|
195
|
+
|
|
196
|
+
```yaml
|
|
197
|
+
---
|
|
198
|
+
template:
|
|
199
|
+
type: package
|
|
200
|
+
name: '@cenk1cenk2/md-printer-template-cv'
|
|
201
|
+
---
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
| `type` | Keys | Description |
|
|
205
|
+
| ----------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
206
|
+
| `builtin` | `name` | The package `@cenk1cenk2/md-printer-template-<name>` from md-printer's own dependencies. |
|
|
207
|
+
| `package` | `name`, `directory?` | An npm package, resolved from the directory of the input file (its `node_modules`, walking up like Node does), then from the current directory, then from md-printer's own dependencies. The package directory is the template directory. `directory` selects a subdirectory of the package instead, and may not leave the package, symlinks included. |
|
|
208
|
+
| `directory` | `path` | A template directory, relative to the directory of the input file. |
|
|
209
|
+
|
|
210
|
+
The same on the command line, where flags win over front-matter. `--template-type` says how to read `-t`, and `--template-directory` is the `directory` of a package. A `--template-type directory` path is relative to the input file too. Without `--template-type`, `-t` is a built-in name or a path as above.
|
|
211
|
+
|
|
212
|
+
```sh
|
|
213
|
+
md-printer document.md --template-type package -t @cenk1cenk2/md-printer-template-cv
|
|
214
|
+
md-printer document.md --template-type package -t my-templates --template-directory letters
|
|
215
|
+
md-printer document.md --template-type builtin -t cv
|
|
216
|
+
md-printer document.md --template-type directory -t ./template
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
An unknown `type`, a missing or unknown key, or a `package` that is not installed fails the run. A package has to allow access to its `package.json`, so one with an `exports` map lists `./package.json` there.
|
|
220
|
+
|
|
162
221
|
### Authoring a template
|
|
163
222
|
|
|
164
|
-
A template is a directory. Pass it with `-t ./path
|
|
223
|
+
A template is a directory. Pass it with `-t ./path`, `template: ./path` or as one of the other [template sources](#template-sources). Its Svelte files and its TypeScript are kept apart, so ESLint, Prettier and tsconfig can target each group:
|
|
165
224
|
|
|
166
225
|
```
|
|
167
226
|
my-template/
|
|
168
|
-
|
|
169
|
-
settings.json
|
|
170
|
-
i18n/
|
|
171
|
-
|
|
227
|
+
package.json optional, see below
|
|
228
|
+
settings.json optional, always at the root
|
|
229
|
+
i18n/ optional, en.yaml, de.json, ...
|
|
230
|
+
template/
|
|
231
|
+
Template.svelte required
|
|
232
|
+
components/*.svelte optional, placed from markdown, see Markdown components
|
|
233
|
+
src/
|
|
234
|
+
extension.ts optional, see Extension module
|
|
235
|
+
*.ts optional, plain modules
|
|
172
236
|
```
|
|
173
237
|
|
|
238
|
+
`files` in `settings.json` moves any of these. Every key is optional and defaults to the layout above:
|
|
239
|
+
|
|
240
|
+
```json
|
|
241
|
+
{
|
|
242
|
+
"files": {
|
|
243
|
+
"template": "template/Template.svelte",
|
|
244
|
+
"components": "template/components",
|
|
245
|
+
"extension": "src/extension.ts",
|
|
246
|
+
"i18n": "i18n"
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
- `components`, `extension` and `i18n` also take an array, read in order: a component of a later folder replaces one of the same name, an export of a later extension module replaces one of the same name, and a key of a later i18n folder replaces the same key while nested keys merge. Use this to share components or translations between templates:
|
|
252
|
+
|
|
253
|
+
```json
|
|
254
|
+
{
|
|
255
|
+
"files": {
|
|
256
|
+
"components": ["template/shared", "template/components"],
|
|
257
|
+
"extension": ["src/format.ts", "src/extension.ts"],
|
|
258
|
+
"i18n": ["i18n/shared", "i18n"]
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
- Paths are relative to the template directory. A path leaving it, a path that does not exist and an unknown key each fail the build.
|
|
264
|
+
- A template written for 3.x keeps working: for each key `files` does not set, when the default location is missing, the root location is used if it exists, that is `Template.svelte`, `components/` and `extension.*`. A path set in `files` never falls back.
|
|
265
|
+
- A package keeps what it does not publish out with an `.npmignore`, as the built-in templates do, for example `release.config.cjs` and `CHANGELOG.md`.
|
|
266
|
+
|
|
174
267
|
`Template.svelte` is a Svelte 5 component receiving these props:
|
|
175
268
|
|
|
176
269
|
| Prop | Description |
|
|
@@ -180,10 +273,15 @@ my-template/
|
|
|
180
273
|
| `t` | i18next translate function, loaded from `i18n/<language>.(yaml\|yml\|json)`. |
|
|
181
274
|
| `language` | The resolved language. |
|
|
182
275
|
| `signature` | `{ date, name?, issuer?, serial? }` while signing is enabled, otherwise `undefined`. |
|
|
276
|
+
| `extension` | The named exports of the [extension module](#extension-module), empty without one. |
|
|
183
277
|
|
|
184
278
|
Set the document title with `<svelte:head><title>...</title></svelte:head>`.
|
|
185
279
|
|
|
186
|
-
|
|
280
|
+
Components may be written in TypeScript with `<script lang="ts">`, and `.ts` modules can be imported, as `./round.js` or `./round.ts`. Svelte strips the types of components, so only type annotations are allowed there, no enums or other TypeScript that emits code; `.ts` modules take full TypeScript. Types are not checked while rendering. The built-in templates are written this way.
|
|
281
|
+
|
|
282
|
+
A template can bring its own dependencies: give the template directory a `package.json` and install it there, as the built-in templates do. Imports in components, `.ts` modules, `@import` in `<style lang="postcss">` and imported images such as `@fortawesome/fontawesome-free/svgs/solid/user.svg` resolve from the template's `node_modules` first and fall back to md-printer's own dependencies. md-printer does not install them for you; a missing one fails the build with the directory to install it in.
|
|
283
|
+
|
|
284
|
+
Styles that need Tailwind CSS v4 or package imports go into a `<style lang="postcss">` block in `Template.svelte` or any component it imports. These blocks are collected and compiled together, so they can `@import 'tailwindcss'` and use `@plugin`, `@theme` and utility classes. Plain `<style>` blocks stay scoped Svelte styles. `@import` of packages (for example `@fontsource/*`, `github-markdown-css`) resolves from the template directory first and then from md-printer's own dependencies, which cover `tailwindcss` and the highlight.js themes. The selected highlight.js theme is always included. Local `url()` and image references are inlined as data URIs.
|
|
187
285
|
|
|
188
286
|
Images are imported, which inlines them as data URIs:
|
|
189
287
|
|
|
@@ -195,6 +293,31 @@ Images are imported, which inlines them as data URIs:
|
|
|
195
293
|
<img src={logo} alt="logo" />
|
|
196
294
|
```
|
|
197
295
|
|
|
296
|
+
#### Extension module
|
|
297
|
+
|
|
298
|
+
A template may contain one extension module, `src/extension.ts`, `.mts`, `.cts`, `.js`, `.mjs` or `.cjs`, so the template can bring its own functions. More than one at the default location fails the build, naming the files; to combine several modules, list them in `files.extension`.
|
|
299
|
+
|
|
300
|
+
```ts
|
|
301
|
+
// src/extension.ts
|
|
302
|
+
export function money(value: number): string {
|
|
303
|
+
return `${value.toFixed(2)} EUR`
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
It is compiled in the same bundle as the template, so TypeScript works and its imports resolve like those of the template's own modules, from its `node_modules` first. Its named exports are available as the `extension` prop of `Template.svelte`, through the `md-printer:extension` context with `getContext`, and in any component with the `getExtension` helper:
|
|
308
|
+
|
|
309
|
+
```svelte
|
|
310
|
+
<script lang="ts">
|
|
311
|
+
import { getExtension } from '@cenk1cenk2/md-printer/components'
|
|
312
|
+
|
|
313
|
+
const { money } = getExtension<typeof import('../../src/extension.js')>()
|
|
314
|
+
</script>
|
|
315
|
+
|
|
316
|
+
<span>{money(12)}</span>
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
The default export is left out. An extension only exposes its exports, md-printer calls none of them by itself. `--preview` rebuilds when the module changes, is added or is removed.
|
|
320
|
+
|
|
198
321
|
#### Shared components
|
|
199
322
|
|
|
200
323
|
Import from `@cenk1cenk2/md-printer/components`:
|
|
@@ -208,7 +331,9 @@ Import from `@cenk1cenk2/md-printer/components`:
|
|
|
208
331
|
| `TotalPages` | Total page count, filled by Chrome. Header and footer only. |
|
|
209
332
|
| `Title` | Document title, filled by Chrome. Header and footer only. |
|
|
210
333
|
| `Date` | Print date, filled by Chrome. Header and footer only. |
|
|
211
|
-
| `
|
|
334
|
+
| `Localized` | Text for the language of the document from props named after languages, `<Localized en="Invoice" de="Rechnung" />` or `:localized{en="Invoice" de="Rechnung"}`, for words that need no entry in `i18n/`. Takes the language, then its base language (`de` for `de-AT`), then `fallback`, otherwise nothing. In a template a prop can also be a snippet for markup. Plain text without a wrapper element. |
|
|
335
|
+
| `Translate` | Text translated with the `i18n/` directory of the template, `<Translate key="present" />` or `::translate{key="present"}`, inline as `:translate{key="present"}`. Plain text without a wrapper element. Optional `fallback` for a missing key, otherwise the key itself is printed. |
|
|
336
|
+
| `SignatureBlock` | Hands the signature, `{ date, name?, issuer?, serial? }`, to its `children` snippet, so the template draws the visible block with its own markup and styles. Takes the `signature` prop, or as `::signature-block` the signature of the document. Renders nothing without a signature or without `children`, so a template gives `::signature-block` its markup with its own `template/components/SignatureBlock.svelte`, see below. |
|
|
212
337
|
|
|
213
338
|
```svelte
|
|
214
339
|
<script>
|
|
@@ -234,10 +359,32 @@ Import from `@cenk1cenk2/md-printer/components`:
|
|
|
234
359
|
|
|
235
360
|
#### Markdown components
|
|
236
361
|
|
|
237
|
-
Every `*.svelte` file in the template's `components/` directory can be placed from markdown, see [Components](#components). The shared components can be placed the same way, for example `::page-break` or `::signature-block`, except `Markdown`.
|
|
362
|
+
Every `*.svelte` file in the template's `template/components/` directory can be placed from markdown, see [Components](#components). The shared components can be placed the same way, for example `::page-break` or `::signature-block`, except `Markdown`.
|
|
363
|
+
|
|
364
|
+
A template replaces or extends any shared component, `SignatureBlock` and `Translate` included, with a file of the same name in `template/components/`:
|
|
365
|
+
|
|
366
|
+
- **Replace:** `template/components/SignatureBlock.svelte` is what `::signature-block` renders from then on. This is about directives: a component that imports `SignatureBlock` from `@cenk1cenk2/md-printer/components` keeps getting the original, so import `./components/SignatureBlock.svelte` to use the replacement in the template itself.
|
|
367
|
+
- **Extend:** that import always reaches md-printer's original, also from a file with the same name, so a component can wrap it:
|
|
368
|
+
|
|
369
|
+
```svelte
|
|
370
|
+
<!-- template/components/SignatureBlock.svelte -->
|
|
371
|
+
<script>
|
|
372
|
+
import { SignatureBlock } from '@cenk1cenk2/md-printer/components'
|
|
373
|
+
|
|
374
|
+
let props = $props()
|
|
375
|
+
</script>
|
|
376
|
+
|
|
377
|
+
<SignatureBlock {...props}>
|
|
378
|
+
{#snippet children(signature)}
|
|
379
|
+
<section class="my-8">
|
|
380
|
+
<strong>Digitally signed</strong> by {signature.name} on {signature.date}
|
|
381
|
+
</section>
|
|
382
|
+
{/snippet}
|
|
383
|
+
</SignatureBlock>
|
|
384
|
+
```
|
|
238
385
|
|
|
239
386
|
```svelte
|
|
240
|
-
<!-- components/Callout.svelte -->
|
|
387
|
+
<!-- template/components/Callout.svelte -->
|
|
241
388
|
<script>
|
|
242
389
|
import { getContext } from 'svelte'
|
|
243
390
|
|
|
@@ -277,7 +424,7 @@ md-printer invoice.yaml -t invoice --sign --sign-certificate ~/id-austria.pem
|
|
|
277
424
|
- Signing only works for PDF output and is skipped with `--preview`.
|
|
278
425
|
- The signing session has to run in your browser. md-printer opens a temporary local page in an app window of the discovered browser, using your normal profile (or with `xdg-open` when none is found), you log in with ID Austria in the A-Trust page, and paste the resulting signature (starts with `MII`) back into the local page. A paste that is cut short is refused on the page, so you can copy it again. It waits until the signature arrives, press Ctrl+C to abort.
|
|
279
426
|
- The returned signature is always verified before it is embedded: its digest must match this document and it must be cryptographically valid. The result is printed with the signer name, serial and issuer. A failed verification fails the run, and with `--log-level debug` the returned signature is written next to the output as `<output>.cms.der`.
|
|
280
|
-
- With a certificate, the signer name, issuer and serial are passed to the template as `signature`, so
|
|
427
|
+
- With a certificate, the signer name, issuer and serial are passed to the template as `signature`, so the template can show who signed and when through `SignatureBlock`. The certificate must be valid at signing time, and the returned signature is rejected if it was not made with it. Without a certificate only the date is available.
|
|
281
428
|
- Verify the result at https://www.signaturpruefung.gv.at.
|
|
282
429
|
|
|
283
430
|
## Migrating from 2.x
|
|
@@ -302,58 +449,67 @@ Renders a markdown or yaml file through a Svelte template into a PDF or HTML doc
|
|
|
302
449
|
USAGE
|
|
303
450
|
$ md-printer [FILE] [OUTPUT] [--log-level
|
|
304
451
|
silent|direct|fatal|error|warn|info|verbose|debug|trace] [-I] [-f
|
|
305
|
-
md|yaml|yml] [-F pdf|html] [-O] [-t <value>] [-
|
|
306
|
-
<value>] [
|
|
307
|
-
|
|
308
|
-
<value>]
|
|
452
|
+
md|yaml|yml] [-F pdf|html] [-O] [-t <value>] [--template-type <value>]
|
|
453
|
+
[--template-directory <value>] [-T <value>] [-l <value>] [-b <value>]
|
|
454
|
+
[--continuous] [-p] [--host 127.0.0.1|localhost|::1] [--port <value>]
|
|
455
|
+
[--open] [--sign] [--sign-provider a-trust] [--sign-certificate <value>]
|
|
309
456
|
|
|
310
457
|
ARGUMENTS
|
|
311
458
|
[FILE] Markdown or yaml file to render.
|
|
312
459
|
[OUTPUT] Output file. Overwrites the one defined in front-matter.
|
|
313
460
|
|
|
314
461
|
FLAGS
|
|
315
|
-
-F, --output-filetype=<option>
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
-I, --stdin
|
|
319
|
-
-O, --stdout
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
--
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
--
|
|
349
|
-
|
|
350
|
-
--
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
--sign-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
462
|
+
-F, --output-filetype=<option> Output file type, defaults to pdf.
|
|
463
|
+
Overwrites the one defined in front-matter.
|
|
464
|
+
<options: pdf|html>
|
|
465
|
+
-I, --stdin Read the input from stdin.
|
|
466
|
+
-O, --stdout Write the output to stdout instead of a
|
|
467
|
+
file.
|
|
468
|
+
-T, --title=<value> Document title. Overwrites the one defined
|
|
469
|
+
in front-matter or the template.
|
|
470
|
+
-b, --browser=<value> Browser executable used for printing.
|
|
471
|
+
Discovered automatically when omitted
|
|
472
|
+
(Brave, Chrome, Chromium, Edge).
|
|
473
|
+
-f, --input-filetype=<option> Input file type. Detected from the file
|
|
474
|
+
extension, markdown for stdin and unknown
|
|
475
|
+
extensions.
|
|
476
|
+
<options: md|yaml|yml>
|
|
477
|
+
-l, --language=<value> Language for template translations.
|
|
478
|
+
Overwrites the one defined in front-matter
|
|
479
|
+
and template settings.
|
|
480
|
+
-p, --preview Rebuild whenever the input, the template or
|
|
481
|
+
its assets change, show the HTML and the PDF
|
|
482
|
+
in a live preview and rewrite the output
|
|
483
|
+
file when there is one.
|
|
484
|
+
-t, --template=<value> Built-in template name or path to a template
|
|
485
|
+
directory, defaults to "default", read as
|
|
486
|
+
--template-type when given. Overwrites the
|
|
487
|
+
one defined in front-matter.
|
|
488
|
+
--continuous Render the PDF as a single continuous page
|
|
489
|
+
without page breaks.
|
|
490
|
+
--host=<option> [default: 127.0.0.1] Loopback host for the
|
|
491
|
+
preview server, it serves the files next to
|
|
492
|
+
the input and is never exposed to the
|
|
493
|
+
network.
|
|
494
|
+
<options: 127.0.0.1|localhost|::1>
|
|
495
|
+
--[no-]open Open the preview window, --no-open keeps
|
|
496
|
+
rebuilding and writing without one.
|
|
497
|
+
--port=<value> Port for the preview server, random when 0.
|
|
498
|
+
--sign Sign the PDF with a qualified electronic
|
|
499
|
+
signature through ID Austria (A-Trust).
|
|
500
|
+
--sign-certificate=<value> Signer certificate (DER or PEM) used for the
|
|
501
|
+
visible signature block and to verify the
|
|
502
|
+
returned signature.
|
|
503
|
+
--sign-provider=<option> Signature provider, defaults to a-trust.
|
|
504
|
+
Overwrites the one defined in front-matter
|
|
505
|
+
and template settings.
|
|
506
|
+
<options: a-trust>
|
|
507
|
+
--template-directory=<value> Directory inside the package to use as the
|
|
508
|
+
template, only valid with --template-type
|
|
509
|
+
package.
|
|
510
|
+
--template-type=<value> How to read --template, one of builtin,
|
|
511
|
+
package or directory, like the type of the
|
|
512
|
+
object form in front-matter.
|
|
357
513
|
|
|
358
514
|
CLI FLAGS
|
|
359
515
|
--log-level=<option> [default: INFO, env: LOG_LEVEL] Set the log level of the
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// \0@oxc-project+runtime@0.
|
|
1
|
+
// \0@oxc-project+runtime@0.157.0/helpers/esm/decorate.js
|
|
2
2
|
function __decorate(decorators, target, key, desc) {
|
|
3
3
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
4
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// \0@oxc-project+runtime@0.
|
|
1
|
+
// \0@oxc-project+runtime@0.157.0/helpers/esm/decorateMetadata.js
|
|
2
2
|
function __decorateMetadata(k, v) {
|
|
3
3
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
4
4
|
}
|
package/dist/commands/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { MdPrinterHandler } from "../modules/md-printer/md-printer.handler.mjs";
|
|
2
2
|
import { MdPrinterModule } from "../modules/md-printer/md-printer.module.mjs";
|
|
3
3
|
import { MdPrinterSchema } from "../modules/md-printer/md-printer.schema.mjs";
|
|
4
|
-
import __decorate from "../_virtual/_@oxc-project_runtime@0.
|
|
4
|
+
import __decorate from "../_virtual/_@oxc-project_runtime@0.157.0/helpers/esm/decorate.mjs";
|
|
5
5
|
import { Args, Command, Flags, UseHandler } from "@cenk1cenk2/oclif-common";
|
|
6
6
|
// src/commands/index.ts
|
|
7
7
|
let MDPrinter = class MDPrinter extends Command {
|
|
@@ -12,6 +12,8 @@ let MDPrinter = class MDPrinter extends Command {
|
|
|
12
12
|
["output-filetype"]: Flags.string({ char: "F" }),
|
|
13
13
|
stdout: Flags.boolean({ char: "O" }),
|
|
14
14
|
template: Flags.string({ char: "t" }),
|
|
15
|
+
["template-type"]: Flags.string(),
|
|
16
|
+
["template-directory"]: Flags.string(),
|
|
15
17
|
title: Flags.string({ char: "T" }),
|
|
16
18
|
language: Flags.string({ char: "l" }),
|
|
17
19
|
browser: Flags.string({ char: "b" }),
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
Text picked by the language of the document from props named after languages, such as `en` and `de`, for words that need no entry in `i18n/`. Takes the
|
|
4
|
+
language as it is, then its base language, then `fallback`. In a template a prop can also be a snippet. Plain text without a wrapper element, like Translate.
|
|
5
|
+
-->
|
|
6
|
+
<script>
|
|
7
|
+
import { getContext } from 'svelte'
|
|
8
|
+
|
|
9
|
+
/** @type {{ fallback?: string | import('svelte').Snippet } & Record<string, string | import('svelte').Snippet | undefined>} */
|
|
10
|
+
let { fallback, ...languages } = $props()
|
|
11
|
+
|
|
12
|
+
/** @type {import('../interfaces/template.interface.js').DocumentContext} */
|
|
13
|
+
const { language } = getContext('md-printer:document')
|
|
14
|
+
|
|
15
|
+
const value = $derived(languages[language] ?? languages[language.split('-')[0]] ?? fallback)
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
{#if typeof value === 'function'}{@render value()}{:else}{value ?? ''}{/if}
|
|
@@ -1,56 +1,18 @@
|
|
|
1
1
|
<!--
|
|
2
2
|
@component
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Passes the signature of a digitally signed document to the `children` snippet, which draws the block, so the template owns its markup and styles. The
|
|
4
|
+
signature comes from the `signature` prop or, as a directive, from the document context. Renders nothing without a signature or without `children`.
|
|
5
5
|
-->
|
|
6
6
|
<script>
|
|
7
|
+
import { getContext } from 'svelte'
|
|
8
|
+
|
|
7
9
|
/**
|
|
8
10
|
* @type {{
|
|
9
|
-
* signature
|
|
10
|
-
*
|
|
11
|
-
* class?: string
|
|
11
|
+
* signature?: import('../interfaces/signature.interface.js').MdPrinterSignature,
|
|
12
|
+
* children?: import('svelte').Snippet<[import('../interfaces/signature.interface.js').MdPrinterSignature]>
|
|
12
13
|
* }}
|
|
13
14
|
*/
|
|
14
|
-
let { signature
|
|
15
|
-
|
|
16
|
-
const text = $derived({
|
|
17
|
-
title: 'Digitally signed',
|
|
18
|
-
by: 'Signed by',
|
|
19
|
-
date: 'Date',
|
|
20
|
-
issuer: 'Certificate',
|
|
21
|
-
verify: 'This document carries a qualified electronic signature. Verify it at',
|
|
22
|
-
...labels
|
|
23
|
-
})
|
|
15
|
+
let { signature = getContext('md-printer:document').signature, children } = $props()
|
|
24
16
|
</script>
|
|
25
17
|
|
|
26
|
-
|
|
27
|
-
<div class="flex items-center gap-3 px-5 py-3 bg-gray-900 text-white">
|
|
28
|
-
<svg class="w-5 h-5 shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
29
|
-
<path d="M12 3l7 3v6c0 4.5-3 7.5-7 9-4-1.5-7-4.5-7-9V6l7-3z" />
|
|
30
|
-
<path d="M9 12l2 2 4-4" />
|
|
31
|
-
</svg>
|
|
32
|
-
<span class="font-extrabold uppercase tracking-wider">{text.title}</span>
|
|
33
|
-
</div>
|
|
34
|
-
<div class="flex flex-col px-5 py-2">
|
|
35
|
-
{#if signature.name}
|
|
36
|
-
<div class="flex justify-between gap-4 py-2">
|
|
37
|
-
<span class="font-semibold text-gray-400">{text.by}</span>
|
|
38
|
-
<span class="font-semibold text-right">{signature.name}</span>
|
|
39
|
-
</div>
|
|
40
|
-
{/if}
|
|
41
|
-
<div class="flex justify-between gap-4 py-2 border-t border-t-gray-100/30">
|
|
42
|
-
<span class="font-semibold text-gray-400">{text.date}</span>
|
|
43
|
-
<span class="text-right">{signature.date}</span>
|
|
44
|
-
</div>
|
|
45
|
-
{#if signature.issuer}
|
|
46
|
-
<div class="flex justify-between gap-4 py-2 border-t border-t-gray-100/30">
|
|
47
|
-
<span class="font-semibold text-gray-400">{text.issuer}</span>
|
|
48
|
-
<span class="text-right text-[0.6rem]">{signature.issuer} · {signature.serial}</span>
|
|
49
|
-
</div>
|
|
50
|
-
{/if}
|
|
51
|
-
</div>
|
|
52
|
-
<p class="px-5 py-3 bg-gray-50 text-[0.6rem] text-gray-400 leading-snug">
|
|
53
|
-
{text.verify}
|
|
54
|
-
<a href="https://www.signaturpruefung.gv.at" class="font-semibold text-gray-900 underline">signaturpruefung.gv.at</a>
|
|
55
|
-
</p>
|
|
56
|
-
</div>
|
|
18
|
+
{#if signature && children}{@render children(signature)}{/if}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
Text translated with the `i18n/` directory of the template. Plain text without a wrapper element, so it flows inside paragraphs and table cells.
|
|
4
|
+
-->
|
|
5
|
+
<script>
|
|
6
|
+
import { getContext } from 'svelte'
|
|
7
|
+
|
|
8
|
+
/** @type {{ key: string, fallback?: string }} */
|
|
9
|
+
let { key, fallback } = $props()
|
|
10
|
+
|
|
11
|
+
/** @type {import('../interfaces/template.interface.js').DocumentContext} */
|
|
12
|
+
const { t } = getContext('md-printer:document')
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
{t(key, { defaultValue: fallback ?? key })}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { getContext } from 'svelte'
|
|
2
|
+
|
|
3
|
+
import type { TemplateExtension } from '../interfaces/template.interface.js'
|
|
4
|
+
|
|
5
|
+
/** The named exports of the extension module of the template, empty without one. */
|
|
6
|
+
export function getExtension<T extends TemplateExtension = TemplateExtension>(): T {
|
|
7
|
+
return getContext('md-printer:extension')
|
|
8
|
+
}
|
package/dist/components/index.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
export { getExtension } from './extension.js'
|
|
1
2
|
export { default as Date } from './Date.svelte'
|
|
3
|
+
export { default as Localized } from './Localized.svelte'
|
|
2
4
|
export { default as Markdown } from './Markdown.svelte'
|
|
3
5
|
export { default as Page } from './Page.svelte'
|
|
4
6
|
export { default as PageBreak } from './PageBreak.svelte'
|
|
@@ -6,3 +8,4 @@ export { default as PageNumber } from './PageNumber.svelte'
|
|
|
6
8
|
export { default as SignatureBlock } from './SignatureBlock.svelte'
|
|
7
9
|
export { default as Title } from './Title.svelte'
|
|
8
10
|
export { default as TotalPages } from './TotalPages.svelte'
|
|
11
|
+
export { default as Translate } from './Translate.svelte'
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// src/constants/attachment.constants.ts
|
|
2
|
+
let AttachmentPosition = /* @__PURE__ */ function(AttachmentPosition) {
|
|
3
|
+
AttachmentPosition["BEFORE"] = "before";
|
|
4
|
+
AttachmentPosition["AFTER"] = "after";
|
|
5
|
+
return AttachmentPosition;
|
|
6
|
+
}({});
|
|
7
|
+
export { AttachmentPosition };
|
package/dist/constants/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AttachmentPosition } from "./attachment.constants.mjs";
|
|
2
|
+
import { 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, TEMPLATE_EXTENSION_FILES, TEMPLATE_LAYOUT, TEMPLATE_PACKAGE_PREFIX, TemplateFiles, TemplateSourceType } from "./template.constants.mjs";
|
|
2
3
|
import { InputFileType, OutputFileType } from "./file.constants.mjs";
|
|
3
4
|
import { PreviewHost } from "./preview.constants.mjs";
|
|
4
5
|
import { SignatureProvider } from "./signature.constants.mjs";
|
|
5
|
-
export { ContextKey, DEFAULT_HIGHLIGHT_STYLE, DEFAULT_LANGUAGE, DEFAULT_PDF_OPTIONS, DEFAULT_TEMPLATE, DIRECTIVE_TAG, Directory, I18N_ACCEPTED_TYPES, InputFileType, MediaType, ModuleSpecifier, OutputFileType, PAGE_BREAK_CLASS, PRINTER_MODULE_OPTIONS, PreviewHost, RenderMode, SignatureProvider, TAILWIND_STYLE_LANG, TemplateFiles };
|
|
6
|
+
export { AttachmentPosition, ContextKey, DEFAULT_HIGHLIGHT_STYLE, DEFAULT_LANGUAGE, DEFAULT_PDF_OPTIONS, DEFAULT_TEMPLATE, DIRECTIVE_TAG, Directory, I18N_ACCEPTED_TYPES, InputFileType, MediaType, ModuleSpecifier, OutputFileType, PAGE_BREAK_CLASS, PRINTER_MODULE_OPTIONS, PreviewHost, RenderMode, SignatureProvider, TAILWIND_STYLE_LANG, TEMPLATE_EXTENSION_FILES, TEMPLATE_LAYOUT, TEMPLATE_PACKAGE_PREFIX, TemplateFiles, TemplateSourceType };
|
|
@@ -4,6 +4,21 @@ let TemplateFiles = /* @__PURE__ */ function(TemplateFiles) {
|
|
|
4
4
|
TemplateFiles["SETTINGS"] = "settings.json";
|
|
5
5
|
return TemplateFiles;
|
|
6
6
|
}({});
|
|
7
|
+
/** Where a template keeps its files unless `files` in its settings says otherwise, the root locations of 3.x come last. */
|
|
8
|
+
const TEMPLATE_LAYOUT = {
|
|
9
|
+
template: ["template/Template.svelte", "Template.svelte"],
|
|
10
|
+
components: ["template/components", "components"],
|
|
11
|
+
extension: ["src", "."],
|
|
12
|
+
i18n: ["i18n"]
|
|
13
|
+
};
|
|
14
|
+
const TEMPLATE_EXTENSION_FILES = [
|
|
15
|
+
"extension.ts",
|
|
16
|
+
"extension.mts",
|
|
17
|
+
"extension.cts",
|
|
18
|
+
"extension.js",
|
|
19
|
+
"extension.mjs",
|
|
20
|
+
"extension.cjs"
|
|
21
|
+
];
|
|
7
22
|
let RenderMode = /* @__PURE__ */ function(RenderMode) {
|
|
8
23
|
RenderMode["BODY"] = "body";
|
|
9
24
|
RenderMode["HEADER"] = "header";
|
|
@@ -15,8 +30,15 @@ let MediaType = /* @__PURE__ */ function(MediaType) {
|
|
|
15
30
|
MediaType["PRINT"] = "print";
|
|
16
31
|
return MediaType;
|
|
17
32
|
}({});
|
|
33
|
+
/** Built-in templates are packages named with this prefix, which md-printer depends on. */
|
|
34
|
+
const TEMPLATE_PACKAGE_PREFIX = "@cenk1cenk2/md-printer-template-";
|
|
35
|
+
let TemplateSourceType = /* @__PURE__ */ function(TemplateSourceType) {
|
|
36
|
+
TemplateSourceType["BUILTIN"] = "builtin";
|
|
37
|
+
TemplateSourceType["PACKAGE"] = "package";
|
|
38
|
+
TemplateSourceType["DIRECTORY"] = "directory";
|
|
39
|
+
return TemplateSourceType;
|
|
40
|
+
}({});
|
|
18
41
|
let Directory = /* @__PURE__ */ function(Directory) {
|
|
19
|
-
Directory["TEMPLATES"] = "templates";
|
|
20
42
|
Directory["COMPONENTS"] = "components";
|
|
21
43
|
Directory["I18N"] = "i18n";
|
|
22
44
|
return Directory;
|
|
@@ -25,6 +47,7 @@ let ModuleSpecifier = /* @__PURE__ */ function(ModuleSpecifier) {
|
|
|
25
47
|
ModuleSpecifier["TEMPLATE"] = "md-printer:template";
|
|
26
48
|
ModuleSpecifier["COMPONENTS"] = "@cenk1cenk2/md-printer/components";
|
|
27
49
|
ModuleSpecifier["TEMPLATE_COMPONENTS"] = "md-printer:template-components";
|
|
50
|
+
ModuleSpecifier["EXTENSION"] = "md-printer:extension";
|
|
28
51
|
return ModuleSpecifier;
|
|
29
52
|
}({});
|
|
30
53
|
let ContextKey = /* @__PURE__ */ function(ContextKey) {
|
|
@@ -32,6 +55,7 @@ let ContextKey = /* @__PURE__ */ function(ContextKey) {
|
|
|
32
55
|
ContextKey["DOCUMENT"] = "md-printer:document";
|
|
33
56
|
ContextKey["MARKDOWN"] = "md-printer:markdown";
|
|
34
57
|
ContextKey["COMPONENTS"] = "md-printer:components";
|
|
58
|
+
ContextKey["EXTENSION"] = "md-printer:extension";
|
|
35
59
|
return ContextKey;
|
|
36
60
|
}({});
|
|
37
61
|
const TAILWIND_STYLE_LANG = "postcss";
|
|
@@ -56,4 +80,4 @@ const DEFAULT_PDF_OPTIONS = {
|
|
|
56
80
|
left: "20mm"
|
|
57
81
|
}
|
|
58
82
|
};
|
|
59
|
-
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 };
|
|
83
|
+
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, TEMPLATE_EXTENSION_FILES, TEMPLATE_LAYOUT, TEMPLATE_PACKAGE_PREFIX, TemplateFiles, TemplateSourceType };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|