diff --git a/README.md b/README.md new file mode 100644 index 0000000..6ea03f4 --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +# Sajt + +It is project that is runring your notes in Mardown format into website + +Layout might be created in pug or html + +Publishing throught SSH (ftp and dav is planned) + +### Initialize project in current directory with default theme + + sajt init + sajt init "Project name" + +### start server + + sajt build + --clean # remove local files that are not revelant to the project anymore + --publish or --serve -p 3000 --watch # Publish or serve with options -p PORT, --watch observe changes and rebuild the page if thare are any + + sajt publish + --override # default is skip, if file exists, do not change it + --clean # remove remote files that not longer exists in the build folder + +### Project structure + +.sajt/config.yaml +.sajt/media # copy all files as they are +.sajt/layouts # pug files that describes the layout the pages + + +### Development + +Install local package + +npm link sajt \ No newline at end of file diff --git a/bin/sajt b/bin/sajt index cd7f5d2..172a0e1 100755 --- a/bin/sajt +++ b/bin/sajt @@ -1,3 +1,5 @@ #!/usr/bin/env node -console.log("hello world update") +console.log("hello i am linked") + +import "../index.js" \ No newline at end of file diff --git a/empty/.sajt/layouts/default.pug b/empty/.sajt/layouts/default.pug new file mode 100644 index 0000000..01ece76 --- /dev/null +++ b/empty/.sajt/layouts/default.pug @@ -0,0 +1,23 @@ +doctype html +html(lang="en") + head + meta(charset="utf-8") + meta(name="viewport" content="width=device-width, initial-scale=1") + title Artur Gurgul - #{title} + meta(name="author" content="Artur Gurgul") + meta(name="description" content="This is my notepad") + + link(rel="shortcut icon" href="/favicon.png") + link(rel="alternate" type="application/atom+xml" title="#{site.data.theme.name}" href="#{site.url}/atom.xml") + link(rel="stylesheet" href="/static/css/all.css") + link(rel="stylesheet" href="/static/css/hightlight.css") + body + .container + .sidebar + include sidebar.pug + .scroll + .content + h1.title= title + #post!= content + .footer + include footer.pug diff --git a/empty/.sajt/layouts/footer.pug b/empty/.sajt/layouts/footer.pug new file mode 100755 index 0000000..b6f0594 --- /dev/null +++ b/empty/.sajt/layouts/footer.pug @@ -0,0 +1,2 @@ +.disclaimer + p © Artur Gurgul, 2024 — Public Domain Licence diff --git a/empty/.sajt/layouts/sidebar.pug b/empty/.sajt/layouts/sidebar.pug new file mode 100755 index 0000000..3f3f644 --- /dev/null +++ b/empty/.sajt/layouts/sidebar.pug @@ -0,0 +1,10 @@ +nav + h2(style="font-size: 20px; margin: 0px;") Hi. I'm + a(href="/") Artur Gurgul + h2(style="font-size: 15px; margin-top: -0.5em;") and this is my notepad. + hr.hr-text(data-content="Contents") + ul#blog-posts.posts + each page in pages.filter(it => it.hidden != true && it.title != undefined ) + li + span » + a(href=page.url, style=(false ? "font-weight: bold;" : ""))= page.title diff --git a/empty/.sajt/media/config.yaml b/empty/.sajt/media/config.yaml new file mode 100644 index 0000000..88f7d81 --- /dev/null +++ b/empty/.sajt/media/config.yaml @@ -0,0 +1,7 @@ +site: + title: Artur Gurgul - {{article.title}} +remote: + type: ssh + user: debian + host: artur.gurgul.pro + path: /var/www/artur.gurgul.pro \ No newline at end of file diff --git a/empty/.sajt/media/static/css/all.css b/empty/.sajt/media/static/css/all.css new file mode 100755 index 0000000..6630bf3 --- /dev/null +++ b/empty/.sajt/media/static/css/all.css @@ -0,0 +1,672 @@ + +@font-face { + font-family: OpenSans; + font-weight: italic; + src: url('/media/opensans/opensans-italic-variable_font_wdth,wght.ttf'); +} + +@font-face { + font-family: OpenSans; + font-weight: normal; + src: url('/media/opensans/opensans-regular-variable_font-wdth,wght.ttf'); +} + +* { + font-family: -apple-system, BlinkMacSystemFont, sans-serif; + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; + font-weight: 500; +} + +.title { + position: sticky; top:0; + background-color: white; +} + +html { + scroll-behavior: smooth; +} + +.container { + position: relative; + /* margin: 0 auto; */ + padding: 0; + display: flex; +} + +.sidebar { + width: 390px; + float: left; +} + +body, +.content, +.container { + box-sizing: border-box; +} + +body, +.container { + height: 100%; +} + +.content { + width: 800px; +} + +.sidebar { + box-sizing: border-box; + border-right: 1px solid #DDD; + height: 100%; + +} +.scroll { + height: 100%; + width: 100%; + overflow-y: scroll +} + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +menu, +nav, +section { + display: block; +} + +body { + line-height: 1; +} + +ol, +ul { + list-style: none; +} + +blockquote, +q { + quotes: none; +} + +blockquote:before, +blockquote:after, +q:before, +q:after { + content: ''; + content: none; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +body { + background: #fff; + font: 14px/21px -apple-system, BlinkMacSystemFont, sans-serif; + color: #444; + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: 100%; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + color: #181818; + font-family: -apple-system, BlinkMacSystemFont, sans-serif; + font-weight: normal; +} + +h1 a, +h2 a, +h3 a, +h4 a, +h5 a, +h6 a { + font-weight: inherit; +} + +h1 { + font-size: 46px; + line-height: 50px; + margin-bottom: 14px; +} + +h2 { + font-size: 35px; + line-height: 40px; + margin-bottom: 10px; +} + +h3 { + font-size: 28px; + line-height: 34px; + margin-bottom: 8px; +} + +h4 { + font-size: 21px; + line-height: 30px; + margin-bottom: 4px; +} + +h5 { + font-size: 17px; + line-height: 24px; +} + +h6 { + font-size: 14px; + line-height: 21px; +} + +.subheader { + color: #777; +} + +p { + margin: 0 0 20px 0; +} + +p img { + margin: 0; +} + +p.lead { + font-size: 21px; + line-height: 27px; + color: #777; +} + +em { + font-style: italic; +} + +strong { + font-weight: bold; + color: #333; +} + +small { + font-size: 80%; +} + +blockquote, +blockquote p { + font-size: 17px; + line-height: 24px; + color: #777; + font-style: italic; +} + +blockquote { + margin: 0px; + padding: 0px 20px 0 15px; + border-left: 2px solid #ddd; +} + +blockquote cite { + display: block; + font-size: 12px; + color: #555; +} + +blockquote cite:before { + content: "\2014 \0020"; +} + +blockquote cite a, +blockquote cite a:visited, +blockquote cite a:visited { + color: #0060ad; +} + +hr { + border: solid #ddd; + border-width: 1px 0 0; + clear: both; + margin: 10px 0 30px; + height: 0; +} + +a, +a:visited { + color: #333; + text-decoration: underline; + outline: 0; +} + +a:hover, +a:focus { + color: #000; +} + +p a, +p a:visited { + line-height: inherit; +} + +ul, +ol { + margin-bottom: 20px; +} + +ul { + list-style: none outside; +} + +ol { + list-style: decimal; +} + +ol, +ul.square, +ul.circle, +ul.disc { + margin-left: 30px; +} + +ul.square { + list-style: square outside; +} + +ul.circle { + list-style: circle outside; +} + +ul.disc { + list-style: disc outside; +} + +ul ul, +ul ol, +ol ol, +ol ul { + margin: 4px 0 5px 30px; + font-size: 90%; +} + +ul ul li, +ul ol li, +ol ol li, +ol ul li { + margin-bottom: 6px; +} + +li { + line-height: 18px; + margin-bottom: 12px; +} + +ul.large li { + line-height: 21px; +} + +li p { + line-height: 21px; +} + +img.scale-with-grid { + max-width: 100%; + height: auto; +} + +ul.tabs { + display: block; + margin: 0 0 20px 0; + padding: 0; + border-bottom: solid 1px #ddd; +} + +ul.tabs li { + display: block; + width: auto; + height: 30px; + padding: 0; + float: left; + margin-bottom: 0; +} + +ul.tabs li a { + display: block; + text-decoration: none; + width: auto; + height: 29px; + padding: 0px 20px; + line-height: 30px; + border: solid 1px #ddd; + border-width: 1px 1px 0 0; + margin: 0; + background: #f5f5f5; + font-size: 13px; +} + +ul.tabs li a.active { + background: #fff; + height: 30px; + position: relative; + top: -4px; + padding-top: 4px; + border-left-width: 1px; + margin: 0 0 0 -1px; + color: #111; +} + +ul.tabs-content { + margin: 0; + display: block; +} + +ul.tabs-content>li { + display: none; +} + +ul.tabs-content>li.active { + display: block; +} + +ul.tabs:before, +ul.tabs:after { + content: '\0020'; + display: block; + overflow: hidden; + visibility: hidden; + width: 0; + height: 0; +} + +ul.tabs:after { + clear: both; +} + +ul.tabs { + zoom: 1; +} + +label span, +legend span { + font-weight: normal; + font-size: 13px; + color: #444; +} + + +thead { + border-bottom: solid #0060ad; + font-weight: bold; + color: #0060ad; +} + +thead th { + padding-left: 20px; + padding-right: 20px; + padding-top: 5px; + padding-bottom: 0px; +} + +tbody td { + padding: 5px; +} + +table { + margin-left: auto; + margin-right: auto; +} + + + +html, +body { + height: 100%; +} + +body { + font-size: 16px; + background-color: white; + color: #222222; + line-height: 24px; + margin: 0; + + border-top: 7px solid #0060ad; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + color: #181818; + font-family: -apple-system, BlinkMacSystemFont, sans-serif; + font-weight: 600; +} + +h1.title { + font-weight: 800; +} + +h1 { + font-size: 32px; + line-height: 40px; +} + +h2 { + font-size: 24px; + line-height: 30px; +} + +h3 { + font-size: 21px; + line-height: 24px; + margin: 1em 0; +} + +ul { + margin: 1em 0; + list-style: disc; +} + +a { + color: #0060ad; + text-decoration: none; +} + +a:hover { + color: #0060ad; + text-decoration: underline; +} + +a:visited { + color: #0060ad; +} + +table { + font-size: inherit; + font: 100%; +} + +img { + display: block; + margin-left: auto; + margin-right: auto; +} + +.posts { + padding: 20px; + } + +ul.posts { + margin-top: 0; + list-style-type: none; + margin-bottom: 10px; +} + +ul.posts li { + line-height: 22px; + font-size: 16px; + margin-bottom: 0px; +} + +ul.posts span { + font-family: 'Lucida Console', 'Andale Mono', monospace; + color: #aaa; + padding-right: 5px; + font-size: 14px; +} + +.site .footer { + font-size: 80%; + color: #666; + border-top: 4px solid #eee; + overflow: hidden; +} + +nav h1, +nav h2 { + text-align: center; +} + +#post pre { + border: 0px solid #ddd; + background-color: #005fad06 !important; + padding: 0 .4em; + margin-bottom: 20px !important; + border-color: #005fad43 !important; +} + +#post ul, +#post ol { + margin-left: 1.35em; +} + +#post code { + border: 1px solid #ddd; + background-color: #eef; + font-size: 85%; + padding: 0 .2em; +} + + +#post pre code { + border: none; +} + +.sidebar { + padding-top: 25px; + font-family: -apple-system, BlinkMacSystemFont, sans-serif; +} + +.sidebar p { + font-weight: 200; +} + +.sidebar a { + font-weight: 600; +} + +text { + font: 500 12px/22px -apple-system, BlinkMacSystemFont, sans-serif; +} + +/* path, rect { + stroke: red; +} */ + +g { + font: 500 12px/22px -apple-system, BlinkMacSystemFont, sans-serif; +} +/* stroke-width="2" */ + +.content { + font: 400 16px/22px -apple-system, BlinkMacSystemFont, sans-serif; + + padding-left: 40px; + padding-top: 25px; + min-height: 400px; +} + +#home h2 { + color: #0060ad; +} + +#post pre { + background-color: white; + border-left: 12px solid #eee; + padding: 0 .8em; +} + +#post code { + background-color: transparent; +} + +#stalker { + float: inherit; +} + +.disclaimer { + color: #aaa; + font-weight: 700; + font-size: smaller; + text-align: center; + padding-top: 40px; + padding-bottom: 10px; +} + + +.highlight { + background-color: white; + color: #586e75; + font-weight: bold; +} + +.highlight .c { + color: #586e75 !important; + font-style: italic !important +} + +p:has(img) { + background-color: #005fad06; + border-left: 12px solid #005fad43; +} + +p > img { + display: block; + margin: 0 auto; + padding-top: 12px; + padding-bottom: 12px; +} + +p:has(svg) { + background-color: #005fad06; + border-left: 12px solid #005fad43; +} + +p > svg { + display: block; + margin: 0 auto; + padding-top: 12px; + padding-bottom: 12px; +} + +pre { + white-space: pre; + overflow: auto; +} + +code, +pre { + font-family: Monaco, Menlo, Consolas, "Courier New", monospace; +} diff --git a/empty/.sajt/media/static/css/hightlight.css b/empty/.sajt/media/static/css/hightlight.css new file mode 100644 index 0000000..d021397 --- /dev/null +++ b/empty/.sajt/media/static/css/hightlight.css @@ -0,0 +1,101 @@ +/* + +XCode style (c) Angel Garcia + +*/ + +.hljs { + background: #fff; + color: black; +} + +/* Gray DOCTYPE selectors like WebKit */ +.xml .hljs-meta { + color: #c0c0c0; +} + +.hljs-comment, +.hljs-quote { + color: #007400; +} + +.hljs-tag, +.hljs-attribute, +.hljs-keyword, +.hljs-selector-tag, +.hljs-literal, +.hljs-name { + color: #aa0d91; +} + +.hljs-variable, +.hljs-template-variable { + color: #3F6E74; +} + +.hljs-code, +.hljs-string, +.hljs-meta .hljs-string { + color: #c41a16; +} + +.hljs-regexp, +.hljs-link { + color: #0E0EFF; +} + +.hljs-title, +.hljs-symbol, +.hljs-bullet, +.hljs-number { + color: #1c00cf; +} + +.hljs-section, +.hljs-meta { + color: #643820; +} + + +.hljs-title.class_, +.hljs-class .hljs-title, +.hljs-type, +.hljs-built_in, +.hljs-params { + color: #5c2699; +} + +.hljs-attr { + color: #836C28; +} + +.hljs-subst { + color: #000; +} + +.hljs-formula { + background-color: #eee; + font-style: italic; +} + +.hljs-addition { + background-color: #baeeba; +} + +.hljs-deletion { + background-color: #ffc8bd; +} + +.hljs-selector-id, +.hljs-selector-class { + color: #9b703f; +} + +.hljs-doctag, +.hljs-strong { + font-weight: bold; +} + +.hljs-emphasis { + font-style: italic; +} \ No newline at end of file diff --git a/empty/.sajt/media/static/images/svgs/apple-mvc.svg b/empty/.sajt/media/static/images/svgs/apple-mvc.svg new file mode 100644 index 0000000..6fc08ee --- /dev/null +++ b/empty/.sajt/media/static/images/svgs/apple-mvc.svg @@ -0,0 +1,4 @@ + + + +UpdateUpdatesControllerUser ActionsViewNotifiesModel \ No newline at end of file diff --git a/empty/.sajt/media/static/images/svgs/classic-mvc.svg b/empty/.sajt/media/static/images/svgs/classic-mvc.svg new file mode 100644 index 0000000..61b7bab --- /dev/null +++ b/empty/.sajt/media/static/images/svgs/classic-mvc.svg @@ -0,0 +1,4 @@ + + + +UpdateUpdatesControllerUser ActionsGets updated stateViewNotifiesModel \ No newline at end of file diff --git a/empty/.sajt/media/static/images/svgs/mvvm.svg b/empty/.sajt/media/static/images/svgs/mvvm.svg new file mode 100644 index 0000000..8edc629 --- /dev/null +++ b/empty/.sajt/media/static/images/svgs/mvvm.svg @@ -0,0 +1,4 @@ + + + +Data bindingUpdatesViewModelView+ UIViewControllerNotifiesModel \ No newline at end of file diff --git a/empty/.sajt/media/static/images/svgs/test-graph.svg b/empty/.sajt/media/static/images/svgs/test-graph.svg new file mode 100644 index 0000000..7214dd9 --- /dev/null +++ b/empty/.sajt/media/static/images/svgs/test-graph.svg @@ -0,0 +1,4 @@ + + + +jhbjjhjhActor \ No newline at end of file diff --git a/empty/.sajt/media/static/images/svgs/viper-ownership.svg b/empty/.sajt/media/static/images/svgs/viper-ownership.svg new file mode 100644 index 0000000..0117eca --- /dev/null +++ b/empty/.sajt/media/static/images/svgs/viper-ownership.svg @@ -0,0 +1,4 @@ + + + +RouterView+ UIViewControllerPresenter owns router interfacePresenter has weak viewPresenterInteractor has weak presenterInteractorServiceServiceEntityEntityView owns PresenterPresenter owns Interactor \ No newline at end of file diff --git a/empty/first-page.md b/empty/first-page.md new file mode 100644 index 0000000..0cf735e --- /dev/null +++ b/empty/first-page.md @@ -0,0 +1,9 @@ +--- +layout: default +title: Content +hidden: true +--- + +# Content + +there is my awasome content \ No newline at end of file diff --git a/empty/index.md b/empty/index.md new file mode 100644 index 0000000..a4971c4 --- /dev/null +++ b/empty/index.md @@ -0,0 +1,8 @@ +--- +layout: default +hidden: true +--- + +# Welcome + +Welcome to my website! \ No newline at end of file diff --git a/index.js b/index.js index 0a69180..34c737b 100644 --- a/index.js +++ b/index.js @@ -1,2 +1,19 @@ +import { Command } from 'commander' +import chalk from 'chalk' +import fs from 'fs-extra' +import path from 'path' +import { newProject, buildProject } from './project.js' -console.log("START") +const program = new Command() + +program + .command('init') + .description('Initialize project in the current directory with the default theme') + .action(newProject) + + program + .command('build') + .description('Build the webpage') + .action(newProject) + +program.parse(process.argv) \ No newline at end of file diff --git a/markdown.js b/markdown.js new file mode 100644 index 0000000..789f626 --- /dev/null +++ b/markdown.js @@ -0,0 +1,53 @@ +const hljs = require('highlight.js') +const { marked } = require('marked') +const { markedHighlight } = require('marked-highlight') +const matter = require('gray-matter') + +marked.use(markedHighlight({ + langPrefix: 'hljs language-', + highlight: function(code, lang) { + const language = hljs.getLanguage(lang) ? lang : 'plaintext'; + return hljs.highlight(code, { language }).value; + } +})) + +function parseMD(file) { + + const fileContents = fs.readFileSync(path.join("./", file), 'utf8') + + const { data: metadata, content: markdownContent } = matter(fileContents) + + const htmlContent = marked(markdownContent) + + return { + meta: metadata, + content: htmlContent + } +} + +const renderer = new marked.Renderer(); +renderer.paragraph = (text) => { + return text.text +} + + +function parseMarkdown(obj) { + for (let key in obj) { + if (typeof obj[key] === 'object' && obj[key] !== null) { + if (Array.isArray(obj[key])) { + for (let i = 0; i < obj[key].length; i++) { + if (typeof obj[key][i] === 'object' && obj[key][i] !== null) { + parseMarkdown(obj[key][i]); + } + else if (typeof obj[key][i] === 'string') { + obj[key][i] = marked(obj[key][i], { renderer }); + } + } + } else { + parseMarkdown(obj[key]); + } + } else if (typeof obj[key] === 'string') { + obj[key] = marked(obj[key], { renderer }); + } + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 107e0b7..41c7dc9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,9 +8,1423 @@ "name": "sajt", "version": "0.0.1", "license": "ISC", + "dependencies": { + "chalk": "^5.3.0", + "commander": "^12.1.0", + "express": "^4.19.2", + "fs-extra": "^11.2.0", + "gray-matter": "^4.0.3", + "highlight.js": "^11.10.0", + "js-yaml": "^4.1.0", + "marked": "^14.0.0", + "marked-highlight": "^2.1.4", + "pug": "^3.0.3", + "ssh2": "^1.15.0", + "ssh2-sftp-client": "^11.0.0" + }, "bin": { "sajt": "bin/sajt" } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz", + "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==", + "dependencies": { + "@babel/types": "^7.25.2" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", + "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", + "dependencies": { + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-never": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/assert-never/-/assert-never-1.3.0.tgz", + "integrity": "sha512-9Z3vxQ+berkL/JJo0dK+EY3Lp0s3NtSnP3VCLsh5HDcZPrh0M+KQRK5sWhUeyPPH+/RCxZqOxLMR+YC6vlviEQ==" + }, + "node_modules/babel-walk": { + "version": "3.0.0-canary-5", + "resolved": "https://registry.npmjs.org/babel-walk/-/babel-walk-3.0.0-canary-5.tgz", + "integrity": "sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==", + "dependencies": { + "@babel/types": "^7.9.6" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/buildcheck": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.6.tgz", + "integrity": "sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==", + "optional": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/character-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", + "integrity": "sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==", + "dependencies": { + "is-regex": "^1.0.3" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "engines": { + "node": ">=18" + } + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/constantinople": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-4.0.1.tgz", + "integrity": "sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==", + "dependencies": { + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.1" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/cpu-features": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.10.tgz", + "integrity": "sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "buildcheck": "~0.0.6", + "nan": "^2.19.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/doctypes": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", + "integrity": "sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/gray-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/gray-matter/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/highlight.js": { + "version": "11.10.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.10.0.tgz", + "integrity": "sha512-SYVnVFswQER+zu1laSya563s+F8VDGt7o35d4utbamowvUNLLMovFqwCLSocpZTz3MgaSRA1IbqRWZv97dtErQ==", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-core-module": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", + "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-expression": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-4.0.0.tgz", + "integrity": "sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==", + "dependencies": { + "acorn": "^7.1.1", + "object-assign": "^4.1.1" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/js-stringify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", + "integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jstransformer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", + "integrity": "sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==", + "dependencies": { + "is-promise": "^2.0.0", + "promise": "^7.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/marked": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-14.0.0.tgz", + "integrity": "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/marked-highlight": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/marked-highlight/-/marked-highlight-2.1.4.tgz", + "integrity": "sha512-D1GOkcdzP+1dzjoColL7umojefFrASDuLeyaHS0Zr/Uo9jkr1V6vpLRCzfi1djmEaWyK0SYMFtHnpkZ+cwFT1w==", + "peerDependencies": { + "marked": ">=4 <15" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/nan": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.20.0.tgz", + "integrity": "sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==", + "optional": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "dependencies": { + "asap": "~2.0.3" + } + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pug": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pug/-/pug-3.0.3.tgz", + "integrity": "sha512-uBi6kmc9f3SZ3PXxqcHiUZLmIXgfgWooKWXcwSGwQd2Zi5Rb0bT14+8CJjJgI8AB+nndLaNgHGrcc6bPIB665g==", + "dependencies": { + "pug-code-gen": "^3.0.3", + "pug-filters": "^4.0.0", + "pug-lexer": "^5.0.1", + "pug-linker": "^4.0.0", + "pug-load": "^3.0.0", + "pug-parser": "^6.0.0", + "pug-runtime": "^3.0.1", + "pug-strip-comments": "^2.0.0" + } + }, + "node_modules/pug-attrs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-3.0.0.tgz", + "integrity": "sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==", + "dependencies": { + "constantinople": "^4.0.1", + "js-stringify": "^1.0.2", + "pug-runtime": "^3.0.0" + } + }, + "node_modules/pug-code-gen": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-3.0.3.tgz", + "integrity": "sha512-cYQg0JW0w32Ux+XTeZnBEeuWrAY7/HNE6TWnhiHGnnRYlCgyAUPoyh9KzCMa9WhcJlJ1AtQqpEYHc+vbCzA+Aw==", + "dependencies": { + "constantinople": "^4.0.1", + "doctypes": "^1.1.0", + "js-stringify": "^1.0.2", + "pug-attrs": "^3.0.0", + "pug-error": "^2.1.0", + "pug-runtime": "^3.0.1", + "void-elements": "^3.1.0", + "with": "^7.0.0" + } + }, + "node_modules/pug-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-2.1.0.tgz", + "integrity": "sha512-lv7sU9e5Jk8IeUheHata6/UThZ7RK2jnaaNztxfPYUY+VxZyk/ePVaNZ/vwmH8WqGvDz3LrNYt/+gA55NDg6Pg==" + }, + "node_modules/pug-filters": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-4.0.0.tgz", + "integrity": "sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==", + "dependencies": { + "constantinople": "^4.0.1", + "jstransformer": "1.0.0", + "pug-error": "^2.0.0", + "pug-walk": "^2.0.0", + "resolve": "^1.15.1" + } + }, + "node_modules/pug-lexer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-5.0.1.tgz", + "integrity": "sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==", + "dependencies": { + "character-parser": "^2.2.0", + "is-expression": "^4.0.0", + "pug-error": "^2.0.0" + } + }, + "node_modules/pug-linker": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-4.0.0.tgz", + "integrity": "sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==", + "dependencies": { + "pug-error": "^2.0.0", + "pug-walk": "^2.0.0" + } + }, + "node_modules/pug-load": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-3.0.0.tgz", + "integrity": "sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ==", + "dependencies": { + "object-assign": "^4.1.1", + "pug-walk": "^2.0.0" + } + }, + "node_modules/pug-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-6.0.0.tgz", + "integrity": "sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==", + "dependencies": { + "pug-error": "^2.0.0", + "token-stream": "1.0.0" + } + }, + "node_modules/pug-runtime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-3.0.1.tgz", + "integrity": "sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==" + }, + "node_modules/pug-strip-comments": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-2.0.0.tgz", + "integrity": "sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ==", + "dependencies": { + "pug-error": "^2.0.0" + } + }, + "node_modules/pug-walk": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-2.0.0.tgz", + "integrity": "sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==" + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/ssh2": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.15.0.tgz", + "integrity": "sha512-C0PHgX4h6lBxYx7hcXwu3QWdh4tg6tZZsTfXcdvc5caW/EMxaB4H9dWsl7qk+F7LAW762hp8VbXOX7x4xUYvEw==", + "hasInstallScript": true, + "dependencies": { + "asn1": "^0.2.6", + "bcrypt-pbkdf": "^1.0.2" + }, + "engines": { + "node": ">=10.16.0" + }, + "optionalDependencies": { + "cpu-features": "~0.0.9", + "nan": "^2.18.0" + } + }, + "node_modules/ssh2-sftp-client": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/ssh2-sftp-client/-/ssh2-sftp-client-11.0.0.tgz", + "integrity": "sha512-lOjgNYtioYquhtgyHwPryFNhllkuENjvCKkUXo18w/Q4UpEffCnEUBfiOTlwFdKIhG1rhrOGnA6DeKPSF2CP6w==", + "dependencies": { + "concat-stream": "^2.0.0", + "promise-retry": "^2.0.1", + "ssh2": "^1.15.0" + }, + "engines": { + "node": ">=18.20.4" + }, + "funding": { + "type": "individual", + "url": "https://square.link/u/4g7sPflL" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/token-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-1.0.0.tgz", + "integrity": "sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==" + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/with": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/with/-/with-7.0.2.tgz", + "integrity": "sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==", + "dependencies": { + "@babel/parser": "^7.9.6", + "@babel/types": "^7.9.6", + "assert-never": "^1.2.1", + "babel-walk": "3.0.0-canary-5" + }, + "engines": { + "node": ">= 10.0.0" + } } } } diff --git a/package.json b/package.json index 6844601..aef98ce 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "sajt", - "version": "0.0.1", + "version": "0.0.2", + "type": "module", "description": "Static site generator based on pug/html and yaml files", "main": "index.js", "scripts": { @@ -26,5 +27,19 @@ "bugs": { "url": "https://github.com/artur-gurgul-pro/sajt/issues" }, - "homepage": "https://github.com/artur-gurgul-pro/sajt#readme" + "homepage": "https://github.com/artur-gurgul-pro/sajt#readme", + "dependencies": { + "chalk": "^5.3.0", + "commander": "^12.1.0", + "express": "^4.19.2", + "fs-extra": "^11.2.0", + "gray-matter": "^4.0.3", + "highlight.js": "^11.10.0", + "js-yaml": "^4.1.0", + "marked": "^14.0.0", + "marked-highlight": "^2.1.4", + "pug": "^3.0.3", + "ssh2": "^1.15.0", + "ssh2-sftp-client": "^11.0.0" + } } diff --git a/project.js b/project.js new file mode 100644 index 0000000..2e94777 --- /dev/null +++ b/project.js @@ -0,0 +1,20 @@ +import { fileURLToPath } from 'url' +import path from 'path' +import { cp } from './utils.js' + +// Get the directory of the current file +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) + +// Path relative to the script file's directory +const DEFAULT_PROJECT_PATH = path.join(__dirname, 'empty') + +export function newProject() { + console.log("Initialize a new project") + console.log(DEFAULT_PROJECT_PATH) + cp(DEFAULT_PROJECT_PATH, ".") +} + +export function buildProject() { + const ignore = [".build", ".site"] +} \ No newline at end of file diff --git a/serve.js b/serve.js new file mode 100644 index 0000000..7a7b007 --- /dev/null +++ b/serve.js @@ -0,0 +1,11 @@ +const express = require('express') +const app = express() +const PORT = process.env.PORT || 3000 + +export function serve() { + app.use(express.static('./.build')) + + app.listen(PORT, () => { + console.log(`Server is running on http://localhost:${PORT}`) + }) +} \ No newline at end of file diff --git a/site b/site index 681042c..fd7f009 100755 --- a/site +++ b/site @@ -1,37 +1,7 @@ -#!/usr/bin/env node - const fs = require('fs') -const yaml = require('js-yaml') -const matter = require('gray-matter') -const { marked } = require('marked') const pug = require('pug') -const hljs = require('highlight.js') -const { markedHighlight } = require('marked-highlight') const path = require('path') -marked.use(markedHighlight({ - langPrefix: 'hljs language-', - highlight: function(code, lang) { - const language = hljs.getLanguage(lang) ? lang : 'plaintext'; - return hljs.highlight(code, { language }).value; - } -})) - -function copyDirectory(source, destination) { - fs.mkdirSync(destination, { recursive: true }) - const items = fs.readdirSync(source) - items.forEach(item => { - const sourceItemPath = path.join(source, item) - const destinationItemPath = path.join(destination, item) - const stat = fs.statSync(sourceItemPath) - if (stat.isDirectory()) { - copyDirectory(sourceItemPath, destinationItemPath) - } else { - fs.copyFileSync(sourceItemPath, destinationItemPath) - } - }) -} - function removeDirectorySync(directory) { try { fs.rmSync(directory, { recursive: true, force: true }) @@ -46,45 +16,6 @@ function readConfig() { return yaml.load(fileContents) } - -function parseMD(file) { - - const fileContents = fs.readFileSync(path.join("./", file), 'utf8') - - const { data: metadata, content: markdownContent } = matter(fileContents) - - const htmlContent = marked(markdownContent) - - return { - meta: metadata, - content: htmlContent - } - - // Combine metadata with HTML content - const completeHtml = ` - - - - - - ${metadata.title} - - - - - - ${htmlContent} - - - `; - - // Save the HTML content to a file - fs.writeFileSync('.build/output.html', completeHtml); - - console.log('Markdown with metadata has been converted to HTML and saved to output.html'); - -} - function compile(template, content, output) { if (template == null) { console.error("Template is not defined") @@ -92,15 +23,10 @@ function compile(template, content, output) { } const compiledFunction = pug.compileFile(`.site/templates/${template}.pug`); const data = { - title: 'Pug Example', - message: 'Hello, Puggi!', - sub: "test", ...content, site: {posts: []} } - //console.log(data) - const dirname = path.dirname(output) if (!fs.existsSync(dirname)) { fs.mkdirSync(dirname, { recursive: true }) @@ -112,7 +38,7 @@ function compile(template, content, output) { } function compileData(template, content, output) { - const compiledFunction = pug.compileFile(`.site/templates/${template}.pug`); + const compiledFunction = pug.compileFile(`.sajt/layouts/${template}.pug`); const dirname = path.dirname(output) if (!fs.existsSync(dirname)) { @@ -124,89 +50,11 @@ function compileData(template, content, output) { console.log(`HTML has been rendered and saved to ${output}`); } -function getAllFilesWithExtension(directory, extension, excludes) { - let results = [] - function readDirectory(directory) { - const items = fs.readdirSync(directory) - - items.forEach(item => { - if(excludes.includes(item)) { - return - } - const itemPath = path.join(directory, item) - const stat = fs.statSync(itemPath) - if (stat.isDirectory()) { - readDirectory(itemPath) - } else if (path.extname(item) === extension) { - results.push(itemPath) - } - }) - } - readDirectory(directory) - return results -} -const Client = require('ssh2-sftp-client') - - -// Read the private key from the default location -const privateKey = fs.readFileSync(path.resolve(process.env.HOME, '.ssh/id_rsa')) - -async function uploadDirectory(serverConfig, localDirPath) { - const sftp = new Client() - await sftp.connect(serverConfig) - try { - await upload(sftp, config, localDirPath, serverConfig.path) - } catch (err) { - console.error(`Error: ${err.message}`) - } finally { - await sftp.end() - console.log('Connection closed') - } -} - -async function upload(sftp, config, localPath, remotePath) { - - console.log('Connected to the server') - - const files = fs.readdirSync(localPath) - - for (const file of files) { - const localFilePath = path.join(localPath, file) - const remoteFilePath = `${remotePath}/${file}` - - if (fs.statSync(localFilePath).isDirectory()) { - await sftp.mkdir(remoteFilePath, true) - await upload(sftp, config, localFilePath, remoteFilePath) - } else { - const fileContent = fs.readFileSync(localFilePath) - await sftp.put(Buffer.from(fileContent), remoteFilePath) - console.log(`File transferred successfully: ${localFilePath}`) -// await sftp.exec(`chown www-data:www-data ${remoteFilePath}`) -// console.log(`Changed owner to www-data for: ${remoteFilePath}`) - } - } - -} - -function pathToArray(filePath) { - // Normalize the file path to handle different OS path separators - const normalizedPath = path.normalize(filePath) - // Split the path into an array of directories - const pathArray = normalizedPath.split(path.sep) - return pathArray -} - - -function parseYML(file) { - const fileContents = fs.readFileSync(file, 'utf8') - return yaml.load(fileContents) -} - -function readMetadata() { +function readMetadata(ignore) { let htmlExtension = "html" - let list = getAllFilesWithExtension('.',".md", [".build", ".site"]) + let list = getAllFilesWithExtension('.',".md", ignore) .map(f => { return { pathMD: f, type: "md", @@ -216,7 +64,7 @@ function readMetadata() { // sites needs to include data from header list = list.concat( - getAllFilesWithExtension('.',".yml", [".build", ".site"]) + getAllFilesWithExtension('.',".yml", ignore) .map(f => { return { pathMD: f, type: "yml", @@ -237,9 +85,6 @@ function readMetadata() { site.path = basePath } - - - // add proper extension const parsedPath = path.parse(site.path) parsedPath.ext = htmlExtension.startsWith('.') ? htmlExtension : `.${htmlExtension}` @@ -254,43 +99,13 @@ function readMetadata() { site.meta = site.md.meta - // For tests - //delete site.md - site.hidden = site.data.hidden || false } return list } -// Custom renderer to avoid unnecessary

tags -const renderer = new marked.Renderer(); -renderer.paragraph = (text) => { - - return text.text -} - -function parseMarkdown(obj) { - for (let key in obj) { - if (typeof obj[key] === 'object' && obj[key] !== null) { - if (Array.isArray(obj[key])) { - for (let i = 0; i < obj[key].length; i++) { - if (typeof obj[key][i] === 'object' && obj[key][i] !== null) { - parseMarkdown(obj[key][i]); - } - else if (typeof obj[key][i] === 'string') { - obj[key][i] = marked(obj[key][i], { renderer }); - } - } - } else { - parseMarkdown(obj[key]); - } - } else if (typeof obj[key] === 'string') { - obj[key] = marked(obj[key], { renderer }); - } - } -} const buildFolder = './.build' @@ -309,8 +124,6 @@ const serverConfig = { privateKey: privateKey, path: config.remote.path } - -console.log(serverConfig) @@ -352,50 +165,6 @@ for(const site of data) { uploadDirectory(serverConfig, buildFolder) -/* -process.exit(0) -// Add watchers - -const chokidar = require('chokidar') -const directoryPath = "." - -// Initialize watcher -const watcher = chokidar.watch(directoryPath, { - ignored: /(^|[\/\\])\../, // ignore dotfiles - persistent: true -}); - - - -// Add event listeners -watcher - .on('add', path => console.log(`File ${path} has been added`)) - .on('change', path => console.log(`File ${path} has been changed`)) - .on('unlink', path => console.log(`File ${path} has been removed`)) - .on('error', error => console.error(`Watcher error: ${error}`)); - -console.log(`Watching for changes in ${directoryPath}`); - - - - - - -*/ - -// Start server - -const express = require('express') -const app = express() -const PORT = process.env.PORT || 3000 - -app.use(express.static('./.build')) -//console.log(path.join(__dirname, '.build')) - -app.listen(PORT, () => { - console.log(`Server is running on http://localhost:${PORT}`) -}); - diff --git a/ssh.js b/ssh.js new file mode 100644 index 0000000..0e52a72 --- /dev/null +++ b/ssh.js @@ -0,0 +1,39 @@ +const Client = require('ssh2-sftp-client') + + +// Read the private key from the default location +const privateKey = fs.readFileSync(path.resolve(process.env.HOME, '.ssh/id_rsa')) + +async function uploadDirectory(serverConfig, localDirPath) { + const sftp = new Client() + await sftp.connect(serverConfig) + try { + await upload(sftp, config, localDirPath, serverConfig.path) + } catch (err) { + console.error(`Error: ${err.message}`) + } finally { + await sftp.end() + console.log('Connection closed') + } +} + +async function upload(sftp, config, localPath, remotePath) { + + console.log('Connected to the server') + + const files = fs.readdirSync(localPath) + + for (const file of files) { + const localFilePath = path.join(localPath, file) + const remoteFilePath = `${remotePath}/${file}` + + if (fs.statSync(localFilePath).isDirectory()) { + await sftp.mkdir(remoteFilePath, true) + await upload(sftp, config, localFilePath, remoteFilePath) + } else { + const fileContent = fs.readFileSync(localFilePath) + await sftp.put(Buffer.from(fileContent), remoteFilePath) + console.log(`File transferred successfully: ${localFilePath}`) + } + } +} \ No newline at end of file diff --git a/utils.js b/utils.js new file mode 100644 index 0000000..de1c94d --- /dev/null +++ b/utils.js @@ -0,0 +1,53 @@ +import yaml from 'js-yaml' +import fs from 'fs' +import path from 'path' + +export function parseYML(file) { + const fileContents = fs.readFileSync(file, 'utf8') + return yaml.load(fileContents) +} + +export function getAllFilesWithExtension(directory, extension, excludes) { + let results = [] + function readDirectory(directory) { + const items = fs.readdirSync(directory) + + items.forEach(item => { + if(excludes.includes(item)) { + return + } + const itemPath = path.join(directory, item) + const stat = fs.statSync(itemPath) + if (stat.isDirectory()) { + readDirectory(itemPath) + } else if (path.extname(item) === extension) { + results.push(itemPath) + } + }) + } + readDirectory(directory) + return results +} + +// copyDirectory +export function cp(source, destination) { + fs.mkdirSync(destination, { recursive: true }) + const items = fs.readdirSync(source) + items.forEach(item => { + const sourceItemPath = path.join(source, item) + const destinationItemPath = path.join(destination, item) + const stat = fs.statSync(sourceItemPath) + if (stat.isDirectory()) { + cp(sourceItemPath, destinationItemPath) + } else { + fs.copyFileSync(sourceItemPath, destinationItemPath) + } + }) +} + +function pathToArray(filePath) { + // Normalize the file path to handle different OS path separators + const normalizedPath = path.normalize(filePath) + // Split the path into an array of directories + return normalizedPath.split(path.sep) +} \ No newline at end of file diff --git a/watch.js b/watch.js new file mode 100644 index 0000000..c187536 --- /dev/null +++ b/watch.js @@ -0,0 +1,20 @@ + +const chokidar = require('chokidar') +const directoryPath = "." + +// Initialize watcher +const watcher = chokidar.watch(directoryPath, { + ignored: /(^|[\/\\])\../, // ignore dotfiles + persistent: true +}); + + + +// Add event listeners +watcher + .on('add', path => console.log(`File ${path} has been added`)) + .on('change', path => console.log(`File ${path} has been changed`)) + .on('unlink', path => console.log(`File ${path} has been removed`)) + .on('error', error => console.error(`Watcher error: ${error}`)); + +console.log(`Watching for changes in ${directoryPath}`);