{"_id":"@davidsneighbour/draft-pipeline","_rev":"5-878b9156708d58322bf19f8d15d611db","name":"@davidsneighbour/draft-pipeline","dist-tags":{"rc":"0.1.1-rc.2","latest":"0.3.0"},"versions":{"0.1.1-rc.0":{"name":"@davidsneighbour/draft-pipeline","version":"0.1.1-rc.0","_id":"@davidsneighbour/draft-pipeline@0.1.1-rc.0","maintainers":[{"name":"davidsneighbour","email":"pkollitsch@gmail.com"}],"bin":{"draft-pipeline":"src/cli.mjs"},"dist":{"shasum":"5ba6e127e8d69987482eed1fca02aa8dfac36a9e","tarball":"https://registry.npmjs.org/@davidsneighbour/draft-pipeline/-/draft-pipeline-0.1.1-rc.0.tgz","fileCount":17,"integrity":"sha512-QHV22ii/8sFQYwOgAovq/19E5/CVFDu4U5v4qlFymJuG7xd/OOin+PLsUtT0VeRFvEOdEJXTORzyUgQatrAVSw==","signatures":[{"sig":"MEQCIFl8GYHEn5q1KlYSgvD3C9ISBGMC0f/KuKoc3Zz6GLu4AiAUl1E+B0Y+V+cGbBNpxOrZe9dUiRumMTBMqyCfBNKjQQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":27669},"type":"module","gitHead":"41559eaa2c84b4d60c3fefd6ce38a1a8ea2fac29","scripts":{"css":"node ./src/cli.mjs css","pdf":"node ./src/cli.mjs pdf","build":"node ./src/cli.mjs build","check":"node --check ./src/*.mjs","upload":"node ./src/cli.mjs upload","release":"release-it --config .release-it.ts","release:pre":"release-it --config .release-it.ts --preRelease=rc"},"_npmUser":{"name":"davidsneighbour","email":"pkollitsch@gmail.com"},"_npmVersion":"11.11.1","description":"Reusable markdown-to-pdf and optional reMarkable upload toolkit","directories":{},"_nodeVersion":"24.14.0","dependencies":{"dotenv":"17.3.1","marked":"17.0.4","fast-glob":"3.3.3","playwright":"1.58.2","gray-matter":"4.0.3","tailwindcss":"4.2.1","@tailwindcss/cli":"4.2.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"release-it":"19.2.4","@release-it/conventional-changelog":"10.0.6"},"_npmOperationalInternal":{"tmp":"tmp/draft-pipeline_0.1.1-rc.0_1773533913010_0.7302156084571609","host":"s3://npm-registry-packages-npm-production"}},"0.1.1-rc.1":{"name":"@davidsneighbour/draft-pipeline","version":"0.1.1-rc.1","_id":"@davidsneighbour/draft-pipeline@0.1.1-rc.1","maintainers":[{"name":"davidsneighbour","email":"pkollitsch@gmail.com"}],"bin":{"draft-pipeline":"src/cli.mjs"},"dist":{"shasum":"965410745bc274a31dbf1bc3f2c5a4b650f11ab9","tarball":"https://registry.npmjs.org/@davidsneighbour/draft-pipeline/-/draft-pipeline-0.1.1-rc.1.tgz","fileCount":21,"integrity":"sha512-pWL1ImI+EnJ2yoxK4L67HTtua992GPAKDNMVG1CIR4rMR20mMHewTWD9qccJsplKpxOw4dIAopsa2kZEJg314w==","signatures":[{"sig":"MEUCIQCWzivHp+UopUb5o6orrI84K2iDPwX5M+4TqXRfx80PpwIgT0K62LwS2+A504q8cIhQc/UfJAGqbpZ5fJKitJXOWEk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":47830},"type":"module","engines":{"node":">=20.12.0"},"gitHead":"200156bbfd608488e2ef5e6498402749f6580822","scripts":{"css":"node ./src/cli.mjs css","pdf":"node ./src/cli.mjs pdf","build":"node ./src/cli.mjs build","check":"node --check ./src/*.mjs","upload":"node ./src/cli.mjs upload","release":"release-it --config .release-it.ts","release:pre":"release-it --config .release-it.ts --preRelease=rc"},"_npmUser":{"name":"davidsneighbour","email":"pkollitsch@gmail.com"},"_npmVersion":"11.11.1","description":"Reusable markdown-to-pdf and optional reMarkable upload toolkit","directories":{},"_nodeVersion":"22.22.1","dependencies":{"marked":"17.0.4","fast-glob":"3.3.3","playwright":"1.58.2","gray-matter":"4.0.3","tailwindcss":"4.2.1","@tailwindcss/cli":"4.2.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"release-it":"19.2.4","@release-it/conventional-changelog":"10.0.6"},"_npmOperationalInternal":{"tmp":"tmp/draft-pipeline_0.1.1-rc.1_1773558339235_0.653413205117114","host":"s3://npm-registry-packages-npm-production"}},"0.1.1-rc.2":{"name":"@davidsneighbour/draft-pipeline","version":"0.1.1-rc.2","_id":"@davidsneighbour/draft-pipeline@0.1.1-rc.2","maintainers":[{"name":"davidsneighbour","email":"pkollitsch@gmail.com"}],"bin":{"draft-pipeline":"src/cli.mjs"},"dist":{"shasum":"b3f41b147f06a204072ef10eeeec36f4c6580844","tarball":"https://registry.npmjs.org/@davidsneighbour/draft-pipeline/-/draft-pipeline-0.1.1-rc.2.tgz","fileCount":25,"integrity":"sha512-rc4AjYQtH40ulJJTp5hyQxq6nONYxOdCe0lEnp52URX3sDbmuluvaPd3rAftux9tXfYMd/pCKF42DhxDgat44g==","signatures":[{"sig":"MEUCIAGzD8BPmpbfjkweerjG0y4cD+tbK82Tm7Ha5IszDPO8AiEAkCH+1yG4t4q8v38UK5XmsIGadjzsVMok7+BBifSUBMo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":52123},"type":"module","engines":{"node":">=20.12.0"},"gitHead":"dd7752a2d888f9439d496f125ec18f94f7fbf48d","scripts":{"css":"node ./src/cli.mjs css","pdf":"node ./src/cli.mjs pdf","build":"node ./src/cli.mjs build","check":"node --check ./src/*.mjs","upload":"node ./src/cli.mjs upload","release":"release-it --config .release-it.ts","release:pre":"release-it --config .release-it.ts --preRelease=rc"},"_npmUser":{"name":"davidsneighbour","email":"pkollitsch@gmail.com"},"_npmVersion":"11.11.1","description":"Reusable markdown-to-pdf and optional reMarkable upload toolkit","directories":{},"_nodeVersion":"22.22.1","dependencies":{"marked":"17.0.4","fast-glob":"3.3.3","playwright":"1.58.2","gray-matter":"4.0.3","tailwindcss":"4.2.1","@tailwindcss/cli":"4.2.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"release-it":"19.2.4","@cspell/dict-en-gb":"5.0.25","@release-it/conventional-changelog":"10.0.6"},"_npmOperationalInternal":{"tmp":"tmp/draft-pipeline_0.1.1-rc.2_1773564609577_0.32448428781972205","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@davidsneighbour/draft-pipeline","version":"0.2.0","_id":"@davidsneighbour/draft-pipeline@0.2.0","maintainers":[{"name":"davidsneighbour","email":"pkollitsch@gmail.com"}],"bin":{"draft-pipeline":"src/cli.mjs"},"dist":{"shasum":"e53734ddcc64b90c7fcd0a11f7c406329efbfd9e","tarball":"https://registry.npmjs.org/@davidsneighbour/draft-pipeline/-/draft-pipeline-0.2.0.tgz","fileCount":25,"integrity":"sha512-DBaY5QT+aL+ug2SjeklRTWjmP22VLkO0pg2AAbNLotSQ6vdfC05GCCdzU/pmJWJlw5we/WTTmFVGXdq+khis8g==","signatures":[{"sig":"MEYCIQDV1+BqtyyFdDv1DwGo4mt6A9+6az7rTKBmjfD3kTSgzwIhALpJRX1hKM3bHSVHZ362XYVzwGd8gNmexHiX4PFotSqf","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":52223},"type":"module","engines":{"node":">=20.12.0"},"gitHead":"de29240451c66445d0789e2205ff0ce6cdd77c5e","scripts":{"css":"node ./src/cli.mjs css","pdf":"node ./src/cli.mjs pdf","build":"node ./src/cli.mjs build","check":"node --check ./src/*.mjs","upload":"node ./src/cli.mjs upload","release":"release-it --config .release-it.ts","release:pre":"release-it --config .release-it.ts --preRelease=rc"},"_npmUser":{"name":"davidsneighbour","email":"pkollitsch@gmail.com"},"_npmVersion":"11.11.1","description":"Reusable markdown-to-pdf and optional reMarkable upload toolkit","directories":{},"_nodeVersion":"22.22.1","dependencies":{"marked":"17.0.4","fast-glob":"3.3.3","playwright":"1.58.2","gray-matter":"4.0.3","tailwindcss":"4.2.1","@tailwindcss/cli":"4.2.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"release-it":"19.2.4","@cspell/dict-en-gb":"5.0.25","@release-it/conventional-changelog":"10.0.6"},"_npmOperationalInternal":{"tmp":"tmp/draft-pipeline_0.2.0_1773565118381_0.4245699771953877","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@davidsneighbour/draft-pipeline","version":"0.3.0","description":"Reusable markdown-to-pdf and optional reMarkable upload toolkit","type":"module","bin":{"draft-pipeline":"src/cli.mjs"},"scripts":{"css":"node ./src/cli.mjs css","pdf":"node ./src/cli.mjs pdf","upload":"node ./src/cli.mjs upload","build":"node ./src/cli.mjs build","check":"node --check ./src/*.mjs","release":"release-it --config .release-it.ts","release:pre":"release-it --config .release-it.ts --preRelease=rc","test":"node --test"},"dependencies":{"@tailwindcss/cli":"4.2.1","fast-glob":"3.3.3","gray-matter":"4.0.3","marked":"17.0.4","playwright":"1.58.2","tailwindcss":"4.2.1"},"devDependencies":{"@cspell/dict-en-gb":"5.0.25","@release-it/conventional-changelog":"10.0.6","release-it":"19.2.4"},"publishConfig":{"access":"public"},"engines":{"node":">=20.12.0"},"gitHead":"8b133223117961245e0ce4e5c597b272105f89ee","_id":"@davidsneighbour/draft-pipeline@0.3.0","_nodeVersion":"22.22.1","_npmVersion":"11.11.1","dist":{"integrity":"sha512-ZDheBQTlwXvGmc4BjS+HelhdxFKtDIvopkpMyXMPkN8srmXMXotZraySWsshyoDZ1CM1dafn4eWUYIuyN9cP6A==","shasum":"f766fc69c4746a4cdece1ac152ed75212fd3bd86","tarball":"https://registry.npmjs.org/@davidsneighbour/draft-pipeline/-/draft-pipeline-0.3.0.tgz","fileCount":26,"unpackedSize":61577,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIAfnhY2f5H3AWj5jBlAp57bW/lMqGsMOjcMEuN2aCkd7AiEAwXK/ppLJuJG2W1uUjMuK24sjeJjp9XpaP1zLe61WsW0="}]},"_npmUser":{"name":"davidsneighbour","email":"pkollitsch@gmail.com"},"directories":{},"maintainers":[{"name":"davidsneighbour","email":"pkollitsch@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/draft-pipeline_0.3.0_1773611255638_0.6115359119091208"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-15T00:18:32.952Z","modified":"2026-03-15T21:47:36.219Z","0.1.1-rc.0":"2026-03-15T00:18:33.168Z","0.1.1-rc.1":"2026-03-15T07:05:39.401Z","0.1.1-rc.2":"2026-03-15T08:50:09.743Z","0.2.0":"2026-03-15T08:58:38.552Z","0.3.0":"2026-03-15T21:47:35.800Z"},"description":"Reusable markdown-to-pdf and optional reMarkable upload toolkit","maintainers":[{"name":"davidsneighbour","email":"pkollitsch@gmail.com"}],"readme":"# @davidsneighbour/draft-pipeline\n\nA standalone package extracted from the `bookofhugo.dev` toolchain for:\n\n1. Markdown to print-style PDF generation.\n2. With Tailwind CSS integration for PDF styling.\n3. Optional upload of built PDFs to a reMarkable tablet and/or any SSH/rsyncable destination.\n\n- [How it works](#how-it-works)\n  - [Markdown to PDF notes](#markdown-to-pdf-notes)\n  - [Upload integrations](#upload-integrations)\n    - [reMarkable integration internals](#remarkable-integration-internals)\n    - [Generic SSH integration](#generic-ssh-integration)\n- [Installation](#installation)\n- [Commands](#commands)\n  - [`draft-pipeline css`](#draft-pipeline-css)\n  - [`draft-pipeline pdf`](#draft-pipeline-pdf)\n  - [`draft-pipeline upload`](#draft-pipeline-upload)\n  - [`draft-piepline build`](#draft-piepline-build)\n- [Configuration](#configuration)\n  - [CLI-only options](#cli-only-options)\n  - [Parameter reference (CLI / env / config)](#parameter-reference-cli--env--config)\n  - [Sensible defaults](#sensible-defaults)\n- [Graceful errors](#graceful-errors)\n\n## How it works\n\n- __Step 1:__ Build Tailwind CSS from `TAILWIND_INPUT_CSS` to `OUTPUT_CSS_FILE`.\n- __Step 2:__ Convert Markdown files from `MARKDOWN_INPUT_DIR` into PDFs in `OUTPUT_DIR` (either n-to-1 or n-to-n generation).\n- __Step 3:__ Run enabled upload integrations.\n\n### Markdown to PDF notes\n\n- The input is a directory tree containing Markdown files (`.md`, `.markdown`).\n- It's front matter is read with [`gray-matter`](https://www.npmjs.com/package/gray-matter).\n- Files with `b/pdf/ignore: true` in the front matter are skipped.\n- Markdown content is rendered via [`marked`](https://www.npmjs.com/package/marked).\n- PDF generation runs through headless [Playwright Chromium](https://www.npmjs.com/package/playwright).\n- Header, footer, and document HTML can be configured using templates.\n- Output PDF names are flattened/sanitized from source path segments and can be in parts configured via front matter.\n\n### Upload integrations\n\nThe upload stage offers integrations to upload (synchronize) the created PDF files to various locations.\n\n- Generic SSH/Rsync integration - (`SSH_UPLOAD_ENABLED=true|false`)\n- reMarkable integration - (`REMARKABLE_UPLOAD_ENABLED=true|false`)\n\nEach integration must be explicitly enabled (`true`).\n\n#### reMarkable integration internals\n\nThis part of the project exists because I, [@davidsneighbour](https://github.com/davidsneighbour) use a reMarkable 2. [reMarkable](https://remarkable.com/) does not ingest plain PDF uploads directly into the library. It requires companion `.metadata` and `.content` JSON files, a UUID for each file, and a folder that the file is copied to. This integration creates those files on the fly, copies all files into the configured xochitl data directory, and finally restarts `xochitl` so the documents appear in the UI. This is relatively slow per file and, depending on the amount of files already on the tablet, the restart takes very long. It's not optimal, but it works. I suggest to create two configurations, one to create the PDF files and one that creates and uploads those files when you want to update the tablet. Or you disconnect your tablet while uploading. The script will fail gracefully when no remarkable is connected.\n\nThis README.md assumes you have your reMarkable tablet set up for SSH access and I call it `remarkable` in my SSH configuration instead of a dynamically assigned IP address. Read the [reMarkable support article for the USB to SSH access](https://remarkable.guide/guide/access/ssh.html) for details on how to set this up. I might write up a guide one day.\n\n#### Generic SSH integration\n\nUploads built PDFs to any SSH target and directory.\n\n- `scp` mode uploads one PDF at a time.\n- `rsync` mode uses include/exclude patterns so only `*.pdf` files are transferred.\n- Both modes are configurable through `SSH_UPLOAD_METHOD=scp|rsync`.\n\n## Installation\n\n```bash\nnpm install @davidsneighbour/draft-pipeline\n```\n\n## Commands\n\n### `draft-pipeline css`\n\nTo be written... creates the css file.\n\n### `draft-pipeline pdf`\n\nTo be written... creates the PDF files.\n\n### `draft-pipeline upload`\n\nTo be written... uploads to configured targets.\n\n### `draft-piepline build`\n\nTo be written... a successive pipeline of `css` > `pdf` > `upload`.\n\n## Configuration\n\nThe pipeline configuration can be changed using .env-variables, a config file, or directly via CLI parameters when you call the tool. To create the env file run the following command:\n\n```bash\nnpx draft-pipeline setup-env --pipeline-env sample.env\n```\n\nLeaving `--pipeline-env` out will save the example to `sample.env`\n\nAll configuration is resolved in this order:\n\n1. Sensible defaults\n1. Environment variables (`.pipeline.env` by default)\n1. JSON config file (`.pipeline.config.json` by default)\n1. CLI flags\n\nLater sources override earlier ones.\n\nPrint the final resolved configuration and where each value came from:\n\n```bash\ndraft-pipeline build --print-config\ndraft-pipeline build --print-config=json\n```\n\n### CLI-only options\n\n- `--pipeline-env <path>`: env file path (default: `.pipeline.env`, will be loaded automatically)\n- `--pipeline-config <path>`: JSON config file path (default: `.pipeline.config.json`)\n- `--print-config[=table|json]`: show resolved config and source mapping, then exit\n\n### Parameter reference (CLI / env / config)\n\n| Purpose                               | CLI                   | Env                             | Config key                   | Default                           |\n| ------------------------------------- | --------------------- | ------------------------------- | ---------------------------- | --------------------------------- |\n| Markdown input dir                    | —                     | `MARKDOWN_INPUT_DIR`            | `markdownInputDir`           | `./book`                          |\n| Output dir                            | —                     | `OUTPUT_DIR`                    | `outputDir`                  | `./dist`                          |\n| Output CSS file                       | —                     | `OUTPUT_CSS_FILE`               | `outputCssFile`              | `./dist/output.css`               |\n| Tailwind input CSS                    | —                     | `TAILWIND_INPUT_CSS`            | `tailwindInputCss`           | `./styles/pdf.css`                |\n| Header template                       | `--header-template`   | `HEADER_TEMPLATE_PATH`          | `headerTemplatePath`         | `./templates/header.html`         |\n| Footer template                       | `--footer-template`   | `FOOTER_TEMPLATE_PATH`          | `footerTemplatePath`         | `./templates/footer.html`         |\n| Document template                     | `--document-template` | `DOCUMENT_TEMPLATE_PATH`        | `documentTemplatePath`       | `./templates/document.html`       |\n| Book layout CSS                       | `--book-layout-css`   | `BOOK_LAYOUT_CSS_PATH`          | `bookLayoutCssPath`          | `./styles/pdf-book-layout.css`    |\n| Print ready mode                      | `--printready`        | `PDF_PRINT_READY`               | `pdfPrintReady`              | `false`                           |\n| PDF bleed                             | `--bleed`             | `PDF_BLEED`                     | `pdfBleed`                   | `3mm`                             |\n| Enable reMarkable upload              | —                     | `REMARKABLE_UPLOAD_ENABLED`     | `remarkableUploadEnabled`    | `false`                           |\n| reMarkable host                       | —                     | `REMARKABLE_HOST`               | `remarkableHost`             | `remarkable`                      |\n| reMarkable xochitl dir                | —                     | `REMARKABLE_XOCHITL_DIR`        | `remarkableXochitlDir`       | `.local/share/remarkable/xochitl` |\n| reMarkable parent folder UUID         | —                     | `REMARKABLE_PARENT_FOLDER_UUID` | `remarkableParentFolderUuid` | empty                             |\n| reMarkable parent folder display name | —                     | `REMARKABLE_PARENT_FOLDER_NAME` | `remarkableParentFolderName` | `Book of Hugo`                    |\n| Enable SSH upload                     | —                     | `SSH_UPLOAD_ENABLED`            | `sshUploadEnabled`           | `false`                           |\n| SSH target (`user@host`)              | —                     | `SSH_TARGET`                    | `sshTarget`                  | empty                             |\n| SSH target dir                        | —                     | `SSH_TARGET_DIR`                | `sshTargetDir`               | empty                             |\n| SSH upload method                     | —                     | `SSH_UPLOAD_METHOD`             | `sshUploadMethod`            | `scp`                             |\n| SSH port                              | —                     | `SSH_PORT`                      | `sshPort`                    | unset                             |\n\n### Sensible defaults\n\nDefaults are chosen to make local development work out-of-the-box with this repository layout:\n\n- source markdown from `./book`\n- write build artifacts to `./dist`\n- use repository-provided templates and CSS\n- disable all uploads by default for safe local runs\n- use `scp` for SSH uploads unless explicitly changed\n- keep print-ready mode disabled unless explicitly enabled\n\n## Graceful errors\n\nThe package intentionally fails with direct explanations when:\n\n- input/template/css files are not readable,\n- no markdown files are found,\n- an upload integration is enabled but its host is unreachable,\n- reMarkable upload is enabled but folder UUID is missing,\n- generic SSH upload is enabled but target settings are missing,\n- no PDFs are available for upload,\n- Tailwind build command fails.\n","readmeFilename":"README.md"}