Add webdav upload script and docs

This commit is contained in:
MassiveBox 2025-03-26 23:13:08 +01:00
parent d6c414f887
commit bf3e635a1c
Signed by: massivebox
GPG key ID: 9B74D3A59181947D
7 changed files with 426 additions and 36 deletions

6
.gitignore vendored
View file

@ -35,5 +35,7 @@ pnpm-debug.log*
!.yarn/versions !.yarn/versions
.pnp.* .pnp.*
# blog # blog, meta
src/content/blog src/content/blog/*
Matomo.astro
src/pages/pages/*

View file

@ -20,13 +20,14 @@ The website will be built to the `./dist` folder.
## Blogging with Joplin ## Blogging with Joplin
You can use Joplin to write and manageyour blog posts, instead of just placing the Markdown files in the You can use Joplin to write and manage your blog posts, instead of just placing the Markdown files in the
`src/content/blog` folder. `src/content/blog` folder.
1. Install [Joplin](https://joplinapp.org/) 1. Install [Joplin](https://joplinapp.org/)
2. Start the Web Clipper Service: Tools > Options > Web Clipper > Start Web Clipper Service 2. Start the Web Clipper Service: Tools > Options > Web Clipper > Start Web Clipper Service
3. Run `npm run joplin` 3. Run `npm run joplin`
4. Allow the request for an API token on the Joplin app 4. Allow the request for an API token on the Joplin app
- You can also place the Joplin token in an `.env` file in the format `JOPLIN_KEY=your_token`.
The script will look for a notebook named `Blog`. It will then download all notes from that notebook, alongside their The script will look for a notebook named `Blog`. It will then download all notes from that notebook, alongside their
attachments, and place them in the `src/content/blog` folder. attachments, and place them in the `src/content/blog` folder.
@ -46,6 +47,22 @@ In order, to have an ogImage (also known as article cover):
``` ```
Note the `.` (dot) instead of `:` (colon)! Note the `.` (dot) instead of `:` (colon)!
## Uploading to WebDav
I have found that a quick and easy way to deploy the website is via WebDav and compatible software on the server side, like
[this](https://github.com/mholt/caddy-webdav) plugin for Caddy.
To simplify uploading to WebDav, I have created a script, which can be run with `npm run upload`.
You have to set the following environment variables:
- `WEBDAV_ENDPOINT`: The URL of the WebDav server, e.g. `https://example.com/webdav/`
- `WEBDAV_USERNAME`: The username for the WebDav server
- `WEBDAV_PASSWORD`: The password for the WebDav server
- `WEBDAV_PATH`: The path to the folder on the server, e.g. `/public_html/` (default: `/`)
The script will upload the `./dist` folder, so make sure you run `npm run build` before the upload script.
Note that running the script will clear the remote folder before uploading the files.
## License ## License
The original [Astro Paper](https://github.com/satnaing/astro-paper) is licensed under the MIT License, Copyright © 2025 The original [Astro Paper](https://github.com/satnaing/astro-paper) is licensed under the MIT License, Copyright © 2025

299
package-lock.json generated
View file

@ -25,7 +25,8 @@
"sass": "^1.77.2", "sass": "^1.77.2",
"satori": "^0.10.11", "satori": "^0.10.11",
"tailwindcss": "^3.4.1", "tailwindcss": "^3.4.1",
"typescript": "^5.4.5" "typescript": "^5.4.5",
"webdav": "^5.8.0"
}, },
"devDependencies": { "devDependencies": {
"@astrojs/react": "^3.0.9", "@astrojs/react": "^3.0.9",
@ -40,6 +41,7 @@
"astro-eslint-parser": "^0.16.2", "astro-eslint-parser": "^0.16.2",
"commitizen": "^4.3.0", "commitizen": "^4.3.0",
"cz-conventional-changelog": "^3.3.0", "cz-conventional-changelog": "^3.3.0",
"dotenv": "^16.4.7",
"eslint": "^8.56.0", "eslint": "^8.56.0",
"eslint-plugin-astro": "^0.31.3", "eslint-plugin-astro": "^0.31.3",
"husky": "^8.0.3", "husky": "^8.0.3",
@ -739,6 +741,15 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@buttercup/fetch": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/@buttercup/fetch/-/fetch-0.2.1.tgz",
"integrity": "sha512-sCgECOx8wiqY8NN1xN22BqqKzXYIG2AicNLlakOAI4f0WgyLVUbAigMf8CZhBtJxdudTcB1gD5lciqi44jwJvg==",
"license": "MIT",
"optionalDependencies": {
"node-fetch": "^3.3.0"
}
},
"node_modules/@commitlint/config-validator": { "node_modules/@commitlint/config-validator": {
"version": "17.6.7", "version": "17.6.7",
"resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-17.6.7.tgz", "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-17.6.7.tgz",
@ -4236,6 +4247,12 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/byte-length": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/byte-length/-/byte-length-1.0.2.tgz",
"integrity": "sha512-ovBpjmsgd/teRmgcPh23d4gJvxDoXtAzEL9xTfMU8Yc2kqCDb7L9jAG0XHl1nzuGl+h3ebCIF1i62UFyA9V/2Q==",
"license": "MIT"
},
"node_modules/cachedir": { "node_modules/cachedir": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz",
@ -4365,6 +4382,15 @@
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
"dev": true "dev": true
}, },
"node_modules/charenc": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
"integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==",
"license": "BSD-3-Clause",
"engines": {
"node": "*"
}
},
"node_modules/cheerio": { "node_modules/cheerio": {
"version": "1.0.0-rc.12", "version": "1.0.0-rc.12",
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz",
@ -4987,6 +5013,15 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/crypt": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
"integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==",
"license": "BSD-3-Clause",
"engines": {
"node": "*"
}
},
"node_modules/css-background-parser": { "node_modules/css-background-parser": {
"version": "0.1.0", "version": "0.1.0",
"resolved": "https://registry.npmjs.org/css-background-parser/-/css-background-parser-0.1.0.tgz", "resolved": "https://registry.npmjs.org/css-background-parser/-/css-background-parser-0.1.0.tgz",
@ -5120,6 +5155,15 @@
"@commitlint/load": ">6.1.1" "@commitlint/load": ">6.1.1"
} }
}, },
"node_modules/data-uri-to-buffer": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
"integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
"license": "MIT",
"engines": {
"node": ">= 12"
}
},
"node_modules/debug": { "node_modules/debug": {
"version": "4.3.4", "version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@ -5470,6 +5514,19 @@
"tslib": "^2.0.3" "tslib": "^2.0.3"
} }
}, },
"node_modules/dotenv": {
"version": "16.4.7",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz",
"integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==",
"dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://dotenvx.com"
}
},
"node_modules/dset": { "node_modules/dset": {
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/dset/-/dset-3.1.3.tgz", "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.3.tgz",
@ -6154,21 +6211,18 @@
"dev": true "dev": true
}, },
"node_modules/fast-xml-parser": { "node_modules/fast-xml-parser": {
"version": "4.2.7", "version": "4.5.3",
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.7.tgz", "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz",
"integrity": "sha512-J8r6BriSLO1uj2miOk1NW0YVm8AGOOu3Si2HQp/cSmo6EA4m3fcwu2WKjJ4RK9wMLBtg69y1kS8baDiQBR41Ig==", "integrity": "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==",
"funding": [ "funding": [
{
"type": "paypal",
"url": "https://paypal.me/naturalintelligence"
},
{ {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/NaturalIntelligence" "url": "https://github.com/sponsors/NaturalIntelligence"
} }
], ],
"license": "MIT",
"dependencies": { "dependencies": {
"strnum": "^1.0.5" "strnum": "^1.1.1"
}, },
"bin": { "bin": {
"fxparser": "src/cli/cli.js" "fxparser": "src/cli/cli.js"
@ -6190,6 +6244,29 @@
"pend": "~1.2.0" "pend": "~1.2.0"
} }
}, },
"node_modules/fetch-blob": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
"integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/jimmywarting"
},
{
"type": "paypal",
"url": "https://paypal.me/jimmywarting"
}
],
"license": "MIT",
"dependencies": {
"node-domexception": "^1.0.0",
"web-streams-polyfill": "^3.0.3"
},
"engines": {
"node": "^12.20 || >= 14.13"
}
},
"node_modules/fflate": { "node_modules/fflate": {
"version": "0.7.4", "version": "0.7.4",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.4.tgz", "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.4.tgz",
@ -6333,6 +6410,18 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/formdata-polyfill": {
"version": "4.0.10",
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
"license": "MIT",
"dependencies": {
"fetch-blob": "^3.1.2"
},
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/fraction.js": { "node_modules/fraction.js": {
"version": "4.3.6", "version": "4.3.6",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.6.tgz", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.6.tgz",
@ -6852,6 +6941,12 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/hot-patcher": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/hot-patcher/-/hot-patcher-2.0.1.tgz",
"integrity": "sha512-ECg1JFG0YzehicQaogenlcs2qg6WsXQsxtnbr1i696u5tLUjtJdQAh0u2g0Q5YV45f263Ta1GnUJsc8WIfJf4Q==",
"license": "MIT"
},
"node_modules/html-escaper": { "node_modules/html-escaper": {
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz",
@ -7654,6 +7749,12 @@
"resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz",
"integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==" "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ=="
}, },
"node_modules/layerr": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/layerr/-/layerr-3.0.0.tgz",
"integrity": "sha512-tv754Ki2dXpPVApOrjTyRo4/QegVb9eVFq4mjqp4+NM5NaX7syQvN5BBNfV/ZpAHCEHV24XdUVrBAoka4jt3pA==",
"license": "MIT"
},
"node_modules/levn": { "node_modules/levn": {
"version": "0.4.1", "version": "0.4.1",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
@ -8433,6 +8534,23 @@
"node": ">= 18" "node": ">= 18"
} }
}, },
"node_modules/md5": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
"integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
"license": "BSD-3-Clause",
"dependencies": {
"charenc": "0.0.2",
"crypt": "0.0.2",
"is-buffer": "~1.1.6"
}
},
"node_modules/md5/node_modules/is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
"license": "MIT"
},
"node_modules/mdast-util-definitions": { "node_modules/mdast-util-definitions": {
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-6.0.0.tgz", "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-6.0.0.tgz",
@ -9505,6 +9623,12 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/nested-property": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/nested-property/-/nested-property-4.0.0.tgz",
"integrity": "sha512-yFehXNWRs4cM0+dz7QxCd06hTbWbSkV0ISsqBfkntU6TOY4Qm3Q88fRRLOddkGh2Qq6dZvnKVAahfhjcUvLnyA==",
"license": "MIT"
},
"node_modules/nlcst-to-string": { "node_modules/nlcst-to-string": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-3.1.1.tgz", "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-3.1.1.tgz",
@ -9545,6 +9669,43 @@
"integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==",
"optional": true "optional": true
}, },
"node_modules/node-domexception": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/jimmywarting"
},
{
"type": "github",
"url": "https://paypal.me/jimmywarting"
}
],
"license": "MIT",
"engines": {
"node": ">=10.5.0"
}
},
"node_modules/node-fetch": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
"integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
"license": "MIT",
"dependencies": {
"data-uri-to-buffer": "^4.0.0",
"fetch-blob": "^3.1.4",
"formdata-polyfill": "^4.0.10"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/node-fetch"
}
},
"node_modules/node-releases": { "node_modules/node-releases": {
"version": "2.0.14", "version": "2.0.14",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
@ -10050,6 +10211,12 @@
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
}, },
"node_modules/path-posix": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/path-posix/-/path-posix-1.0.0.tgz",
"integrity": "sha512-1gJ0WpNIiYcQydgg3Ed8KzvIqTsDpNwq+cjBCssvBtuTWjEqY1AW+i+OepiEMqDCzyro9B2sLAe4RBPajMYFiA==",
"license": "ISC"
},
"node_modules/path-to-regexp": { "node_modules/path-to-regexp": {
"version": "6.2.1", "version": "6.2.1",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz",
@ -10690,6 +10857,12 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/querystringify": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
"license": "MIT"
},
"node_modules/queue-microtask": { "node_modules/queue-microtask": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@ -11033,6 +11206,12 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/requires-port": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
"license": "MIT"
},
"node_modules/resolve": { "node_modules/resolve": {
"version": "1.22.4", "version": "1.22.4",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz",
@ -12265,9 +12444,16 @@
} }
}, },
"node_modules/strnum": { "node_modules/strnum": {
"version": "1.0.5", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz",
"integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/NaturalIntelligence"
}
],
"license": "MIT"
}, },
"node_modules/strtok3": { "node_modules/strtok3": {
"version": "7.0.0", "version": "7.0.0",
@ -13175,6 +13361,25 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"node_modules/url-join": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz",
"integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==",
"license": "MIT",
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
}
},
"node_modules/url-parse": {
"version": "1.5.10",
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
"license": "MIT",
"dependencies": {
"querystringify": "^2.1.1",
"requires-port": "^1.0.0"
}
},
"node_modules/util-deprecate": { "node_modules/util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@ -13897,6 +14102,76 @@
"url": "https://github.com/sponsors/wooorm" "url": "https://github.com/sponsors/wooorm"
} }
}, },
"node_modules/web-streams-polyfill": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
"integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
"license": "MIT",
"engines": {
"node": ">= 8"
}
},
"node_modules/webdav": {
"version": "5.8.0",
"resolved": "https://registry.npmjs.org/webdav/-/webdav-5.8.0.tgz",
"integrity": "sha512-iuFG7NamJ41Oshg4930iQgfIpRrUiatPWIekeznYgEf2EOraTRcDPTjy7gIOMtkdpKTaqPk1E68NO5PAGtJahA==",
"license": "MIT",
"dependencies": {
"@buttercup/fetch": "^0.2.1",
"base-64": "^1.0.0",
"byte-length": "^1.0.2",
"entities": "^6.0.0",
"fast-xml-parser": "^4.5.1",
"hot-patcher": "^2.0.1",
"layerr": "^3.0.0",
"md5": "^2.3.0",
"minimatch": "^9.0.5",
"nested-property": "^4.0.0",
"node-fetch": "^3.3.2",
"path-posix": "^1.0.0",
"url-join": "^5.0.0",
"url-parse": "^1.5.10"
},
"engines": {
"node": ">=14"
}
},
"node_modules/webdav/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/webdav/node_modules/entities": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz",
"integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/webdav/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/whatwg-encoding": { "node_modules/whatwg-encoding": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",

View file

@ -13,7 +13,8 @@
"cz": "cz", "cz": "cz",
"prepare": "husky install", "prepare": "husky install",
"lint": "eslint .", "lint": "eslint .",
"joplin": "node src/utils/joplin.js" "joplin": "node src/utils/joplin.mjs",
"upload": "node src/utils/upload.mjs"
}, },
"dependencies": { "dependencies": {
"@astrojs/check": "^0.7.0", "@astrojs/check": "^0.7.0",
@ -33,7 +34,8 @@
"sass": "^1.77.2", "sass": "^1.77.2",
"satori": "^0.10.11", "satori": "^0.10.11",
"tailwindcss": "^3.4.1", "tailwindcss": "^3.4.1",
"typescript": "^5.4.5" "typescript": "^5.4.5",
"webdav": "^5.8.0"
}, },
"devDependencies": { "devDependencies": {
"@astrojs/react": "^3.0.9", "@astrojs/react": "^3.0.9",
@ -48,6 +50,7 @@
"astro-eslint-parser": "^0.16.2", "astro-eslint-parser": "^0.16.2",
"commitizen": "^4.3.0", "commitizen": "^4.3.0",
"cz-conventional-changelog": "^3.3.0", "cz-conventional-changelog": "^3.3.0",
"dotenv": "^16.4.7",
"eslint": "^8.56.0", "eslint": "^8.56.0",
"eslint-plugin-astro": "^0.31.3", "eslint-plugin-astro": "^0.31.3",
"husky": "^8.0.3", "husky": "^8.0.3",

View file

@ -1,12 +1 @@
<script is:inline> <script defer src="https://stats.massive.box/p.js" data-website-id="30344937-ffdf-4a6a-ba52-dc60a23aa4f2"></script>
var _paq = _paq || [];
_paq.push(["trackPageView"]), _paq.push(["enableLinkTracking"]),
function() {
_paq.push(["setTrackerUrl", "//stats.massive.box/sjprfvo.php"]);
_paq.push(["setSiteId", "1"]);
_paq.push(['disableAlwaysUseSendBeacon', 'true']);
var a = document, r = a.createElement("script"), s = a.getElementsByTagName("script")[0];
r.async = !0, r.defer = !0, r.src = "//stats.massive.box/fauqtkg.php", s.parentNode.insertBefore(r, s)
}();
</script>
<noscript><img src="//stats.massive.box/sjprfvo.php?dzp=1&opl=1" /></noscript>

View file

@ -1,6 +1,12 @@
const http = require('node:http'); import dotenv from 'dotenv';
const fs = require('fs'); dotenv.config();
const path = require('path');
import http from 'node:http';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
async function fetch(url, method = "GET") { async function fetch(url, method = "GET") {
return new Promise((resolve) => { return new Promise((resolve) => {
@ -172,16 +178,18 @@ async function clearBlogFolder() {
} }
async function main() { async function main() {
console.log("Finding JoplinClipperServer port..."); console.log("Finding JoplinClipperServer port...");
let host = "http://localhost:" + await findPort(); let host = "http://localhost:" + await findPort();
let apiToken = await authenticate(host);
//let apiToken = ""; let apiToken = process.env.JOPLIN_KEY;
if (!apiToken) {
apiToken = await authenticate(host);
}
let notes = await getNotebookNotes(apiToken, host); let notes = await getNotebookNotes(apiToken, host);
await clearBlogFolder(); await clearBlogFolder();
for(let noteId of notes) { for(let noteId of notes) {
let noteBody = await getNoteBody(apiToken, host, noteId); let noteBody = await getNoteBody(apiToken, host, noteId);
let slug = await getNoteSlug(noteBody); let slug = await getNoteSlug(noteBody);

96
src/utils/upload.mjs Normal file
View file

@ -0,0 +1,96 @@
import dotenv from 'dotenv';
dotenv.config();
import { createClient } from 'webdav';
import fs from 'fs';
import path from 'path';
const client = createClient(
process.env.WEBDAV_ENDPOINT,
{
username: process.env.WEBDAV_USERNAME,
password: process.env.WEBDAV_PASSWORD,
maxBodyLength: Infinity,
maxContentLength: Infinity,
headers: {
Accept: "*/*",
Connection: "keep-alive"
}
}
);
async function createDirectoryIfNotExist(remotePath) {
try {
const exists = await client.exists(remotePath);
if (!exists) {
await client.createDirectory(remotePath);
}
} catch (error) {
if (error.status !== 409 && error.status !== 405) {
throw error;
}
}
}
async function uploadDirectory(localPath, remoteBasePath) {
try {
const items = fs.readdirSync(localPath, { withFileTypes: true });
for (const item of items) {
const localItemPath = path.join(localPath, item.name);
const remoteItemPath = path.posix.join(remoteBasePath, item.name);
if (item.isDirectory()) {
// Create directory on WebDAV server
await createDirectoryIfNotExist(remoteItemPath);
console.log(`Verified directory: ${remoteItemPath}`);
await uploadDirectory(localItemPath, remoteItemPath);
} else {
// Upload file
console.log(`Uploading file: ${remoteItemPath}`);
const content = fs.readFileSync(localItemPath);
await client.putFileContents(remoteItemPath, content);
}
}
} catch (error) {
console.error(`Error processing ${localPath}:`, error.message);
throw error;
}
}
async function clearFolder(remotePath) {
try {
const items = await client.getDirectoryContents(remotePath);
for (const item of items) {
if (item.basename !== '..') {
const itemPath = path.posix.join(remotePath, item.basename);
await client.deleteFile(itemPath);
}
}
} catch (error) {
console.error('Error clearing root folder:', error.message);
throw error;
}
}
// Usage example
async function main() {
const localDir = './dist';
let remoteDir = process.env.WEBDAV_REMOTE_DIR;
if(remoteDir === undefined) {
remoteDir = '/';
}
try {
// Clear root folder
await clearFolder(remoteDir);
// Upload new content
await uploadDirectory(localDir, remoteDir);
console.log('Directory upload complete');
} catch (error) {
console.error('Upload failed:', error.message);
}
}
main();