WIP
This commit is contained in:
parent
374e79cfb4
commit
d086c1d493
25 changed files with 2539 additions and 239 deletions
35
README.md
Normal file
35
README.md
Normal file
|
@ -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
|
4
bin/sajt
4
bin/sajt
|
@ -1,3 +1,5 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
console.log("hello world update")
|
||||
console.log("hello i am linked")
|
||||
|
||||
import "../index.js"
|
23
empty/.sajt/layouts/default.pug
Normal file
23
empty/.sajt/layouts/default.pug
Normal file
|
@ -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
|
2
empty/.sajt/layouts/footer.pug
Executable file
2
empty/.sajt/layouts/footer.pug
Executable file
|
@ -0,0 +1,2 @@
|
|||
.disclaimer
|
||||
p © Artur Gurgul, 2024 — Public Domain Licence
|
10
empty/.sajt/layouts/sidebar.pug
Executable file
10
empty/.sajt/layouts/sidebar.pug
Executable file
|
@ -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
|
7
empty/.sajt/media/config.yaml
Normal file
7
empty/.sajt/media/config.yaml
Normal file
|
@ -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
|
672
empty/.sajt/media/static/css/all.css
Executable file
672
empty/.sajt/media/static/css/all.css
Executable file
|
@ -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;
|
||||
}
|
101
empty/.sajt/media/static/css/hightlight.css
Normal file
101
empty/.sajt/media/static/css/hightlight.css
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
|
||||
XCode style (c) Angel Garcia <angelgarcia.mail@gmail.com>
|
||||
|
||||
*/
|
||||
|
||||
.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;
|
||||
}
|
4
empty/.sajt/media/static/images/svgs/apple-mvc.svg
Normal file
4
empty/.sajt/media/static/images/svgs/apple-mvc.svg
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Do not edit this file with editors other than draw.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="473px" height="187px" viewBox="-0.5 -0.5 473 187" content="<mxfile host="Electron" modified="2023-11-07T18:35:04.577Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.0.3 Chrome/114.0.5735.289 Electron/25.8.4 Safari/537.36" version="22.0.3" etag="K1wkrmuddXaPyJl6GV6f" type="device"><diagram name="Page-1" id="i07ux6VTKLeM-OTNBLxs">5ZhNU9swEIZ/TY5k/BHHzjEf0B5oywzTFo7CVhwVxeuRFZLw6yvZq9iOTYCEQEpPWK9Wa0n76kFxxx3PV18ESWffIKK841jRquNOOo5jB/2B+qOVNSpKKpRYsAi1UrhmjxRFC9UFi2hWC5QAXLK0LoaQJDSUNY0IAct62BR4/a0piWlDuA4Jb6q/WSRnhRo4fql/pSyemTfbZsVzYoJxJdmMRLCsSO55xx0LAFk8zVdjyvXumX0pxl080buZmKCJfMkApxjwQPgC14bzkmuzWBqptWMThJxBDAnh56U6ErBIIqozWqpVxlwCpEq0lfiHSrnGQpKFBCWpGYr1jR7UdTzTvsUkeWOyqrXW2JpCIsfAQeTzcy2rbxH18lEmBdzTp3tMqRzMYRal50c4ixP1HKpXUTV8xMkd5VeQMcmg1vFAhWTKCpdbAXMWRflumIAhptx05ClHJLyP8w0zE00g0b3FvuvNrpUyg4UIUcJDIomIKVZ30Cy4vbGROoAU5lTtnQoRlBPJHurZCR6EeBOHQ4dCkHUlIAWWyKyS+UoLKgAPtRP4Xa/IiYfaDZyq89RDkdO0KpMrpdyd7U51G079mUZE0la/5sVpK+t2ce5ASphrD9OMPZK7PIk2GS5YZfRGHW/Sbruh1mcg2KPqIxy9tL91spSELIlHOKky2zOu0YnpqtOCPlxRCZyqU5x2p2Aiq2sFWENT0zNM/jovlWYxITCdZsrBdXu81hC9k0DXoeQaTlpo1ORVK9vysXTF5A2O08+3FaKqZjkT3TATOQaKbOftWVSzxw4veE/AIfvMdHCPS4feTjqcKY/1A++EeNBveGCs9l0A52p7t21QP/dTxvnW1ul6XpA54/rI/EhposZfkyQ70v1jzzq+4KzhgJ7T+Aft44FdlldY2xhhVrm+9q3DD6j/gbBGQFpd36sycicgS8LX+I4p3hnxB9N60KR1/+NgHTRhnekjag1DjbxPzez+cZntP3Ojc3y/V7/RuYcRfN064E14PmjY5Bejy+dIvgPb7ZD/50jueNsk7w3ekeTmG8zHotzZA+X2UVHeFtl0y8EoN7fsE2G5bTfc8B0km7LPffW27VK8pFO96WfOS39Y7cl222qvaXkht/2gDvdT+rlujFtxCn4Z/t+B3rfeE+iqWX5eLupYfqV3z/8C</diagram></mxfile>"><defs/><g><path d="M 170.5 15 L 30.53 15 L 30.5 116.76" fill="none" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 30.5 122.76 L 26.5 114.76 L 30.5 116.76 L 34.5 114.76 Z" fill="#0060ad" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g fill="#0060AD" font-family="Helvetica" text-anchor="middle" font-size="10.999999999999998px"><text x="34.74" y="8.55">Update</text></g><path d="M 290.5 20 L 410.53 20.05 L 410.5 116.76" fill="none" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 410.5 122.76 L 406.5 114.76 L 410.5 116.76 L 414.5 114.77 Z" fill="#0060ad" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g fill="#0060AD" font-family="Helvetica" text-anchor="middle" font-size="10.999999999999998px"><text x="372.63" y="12.59">Updates</text></g><rect x="170.5" y="5" width="120" height="60" fill="none" stroke="#0060ad" stroke-width="2" pointer-events="all"/><g fill="#0060ad" font-family="Open Sans" font-weight="bold" text-anchor="middle" font-size="11.999999999999998px"><text x="230" y="39.5">Controller</text></g><path d="M 90.5 125 L 90.53 50.05 L 162.26 50.01" fill="none" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 168.26 50 L 160.27 54.01 L 162.26 50.01 L 160.26 46.01 Z" fill="#0060ad" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g fill="#0060AD" font-family="Helvetica" text-anchor="middle" font-size="10.999999999999998px"><text x="114.55" y="43.59">User Actions</text></g><rect x="0.5" y="125" width="120" height="60" fill="none" stroke="#0060ad" stroke-width="2" pointer-events="all"/><g fill="#0060ad" font-family="Open Sans" font-weight="bold" text-anchor="middle" font-size="11.999999999999998px"><text x="60" y="159.5">View</text></g><path d="M 380.5 125 L 380.53 50.05 L 298.74 50" fill="none" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 292.74 50 L 300.74 46.01 L 298.74 50 L 300.73 54.01 Z" fill="#0060ad" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g fill="#0060AD" font-family="Helvetica" text-anchor="middle" font-size="10.999999999999998px"><text x="371.55" y="42.18">Notifies</text></g><rect x="350.5" y="125" width="120" height="60" fill="none" stroke="#0060ad" stroke-width="2" pointer-events="all"/><g fill="#0060ad" font-family="Open Sans" font-weight="bold" text-anchor="middle" font-size="11.999999999999998px"><text x="410" y="159.5">Model</text></g></g></svg>
|
After Width: | Height: | Size: 4.5 KiB |
4
empty/.sajt/media/static/images/svgs/classic-mvc.svg
Normal file
4
empty/.sajt/media/static/images/svgs/classic-mvc.svg
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Do not edit this file with editors other than draw.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="473px" height="186px" viewBox="-0.5 -0.5 473 186" content="<mxfile host="Electron" modified="2023-11-07T18:34:22.657Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.0.3 Chrome/114.0.5735.289 Electron/25.8.4 Safari/537.36" version="22.0.3" etag="Iz-bp9UTBWzNTIIgo6GH" type="device"><diagram name="Page-1" id="xkBbz92YaXBT8ljpGPb4">7VlbV6MwEP41fdQDoRf62Iu6D+6u53j29phCSrOmDCektvXXbwJJIQUrWmvr6hPky2RIMt98DKHljearK46T2VcICWshJ1y1vHELIdfv9uVFIWuNSChHIk5DjRXALX0gGnQ0uqAhSS1DAcAETWwwgDgmgbAwzDksbbMpMPupCY5IBbgNMKuiv2goZjnqo16BfyE0mpknu2bFc2yM9UrSGQ5hWYK8i5Y34gAiv5uvRoSp3TP7ko+7fKR3MzFOYtFkAMoH3GO20GvT8xJrs1gSyrXrJnAxgwhizC4KdMhhEYdEeXRkq7C5Bkgk6ErwLxFirQOJFwIkJGfI17/VoHPUMe0/2knWGK+s1lq3phCLETDg2fw8x+k6WD58mAoOd+TxHhMqpH2YRan5YUajWN4H8lFEDh8yPCHsBlIqKFgd94QLKqlwvWUwp2GY7YYxGGiXm47M5RAHd1G2YWaiMcSqN993tdlWKFNY8EBDOkkE5hHZUKsacXfDI5mBBOZEbp404YRhQe9t91hnQrSx00MHnON1ySABGou05PlGAdJAZzXyNaN1Tvct3smb3KFplWZWQBk363nqVXj6IwmxILVszUJTF9Tt0ExACJgrBpOUPuBJ5kRRTK9WeuwMW51xPekGCp8Bpw+yDzPNpJcTpwk/lBOyatWInJ59IS1lSqB6SmhHzrnj+8gK35l2/jzSFKwwJjCdppKrNhWeG/z2SYjUvho1GNfoTlWZalUsG3sQ/Wi/vn5Ykd4R1s4jOZ1+JnWjpG7vTOoz+Vrt+p0TSuNuJd4jucccGJNbuR1yO12nlLGtrVOxu8RzylTKfU9ILMff4jg9UIHwwjg2yCs9oI3sF6h5ny6LAtM1JrNScdl19s/E3hEFdkVFrq+9jm5u9FXeF/KqGkZdC1W2NFm7eG+ybGq4si53jyfLflWWU5WgziBQ4vZfqXOa4IDG0VBPatw+rGL3nijDUK/Xtsswbz/9XtcOeBU17x9fM9yyYBT68VE145i1nDmZKdHhiqjvRWeR1XRhxozPD7amStF/Qilc37wiTqK0M3Qshf8nJcunqrodJVx9wffuqjrUsas65LxhWece83TP1HWWRqOGGu3aGo1eV6PrLKtc2V+j2zUafYDzusZ0qB6ifQNBp/Tzi7uhKru7z9HkJ7fb8+0C7pTO0dzqQZr+OfPRZbrrvJ1My2bxfyePYvGbzLv4Bw==</diagram></mxfile>"><defs/><g><path d="M 171 14 L 31.05 14 L 31 115.76" fill="none" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 31 121.76 L 27 113.76 L 31 115.76 L 35 113.77 Z" fill="#0060ad" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g fill="#0060AD" font-family="Helvetica" text-anchor="middle" font-size="10.999999999999998px"><text x="35.24" y="8.55">Update</text></g><path d="M 291 34 L 410.95 34 L 411 115.76" fill="none" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 411 121.76 L 406.99 113.77 L 411 115.76 L 414.99 113.76 Z" fill="#0060ad" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g fill="#0060AD" font-family="Helvetica" text-anchor="middle" font-size="10.999999999999998px"><text x="367.87" y="29.55">Updates</text></g><rect x="171" y="4" width="120" height="60" fill="none" stroke="#0060ad" stroke-width="2" pointer-events="all"/><g fill="#0060ad" font-family="Open Sans" font-weight="bold" text-anchor="middle" font-size="11.999999999999998px"><text x="230.5" y="38.5">Controller</text></g><path d="M 91 124 L 90.95 49.05 L 162.76 49.01" fill="none" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 168.76 49 L 160.77 53.01 L 162.76 49.01 L 160.76 45.01 Z" fill="#0060ad" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g fill="#0060AD" font-family="Helvetica" text-anchor="middle" font-size="10.999999999999998px"><text x="114.98" y="44.59">User Actions</text></g><path d="M 121 169 L 342.76 169" fill="none" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 348.76 169 L 340.76 173 L 342.76 169 L 340.76 165 Z" fill="#0060ad" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g fill="#0060AD" font-family="Helvetica" text-anchor="middle" font-size="10.999999999999998px"><text x="256.82" y="164.55">Gets updated state</text></g><rect x="1" y="124" width="120" height="60" fill="none" stroke="#0060ad" stroke-width="2" pointer-events="all"/><g fill="#0060ad" font-family="Open Sans" font-weight="bold" text-anchor="middle" font-size="11.999999999999998px"><text x="60.5" y="158.5">View</text></g><path d="M 351 139 L 129.24 139" fill="none" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 123.24 139 L 131.24 135 L 129.24 139 L 131.24 143 Z" fill="#0060ad" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g fill="#0060AD" font-family="Helvetica" text-anchor="middle" font-size="10.999999999999998px"><text x="256.29" y="133.55">Notifies</text></g><rect x="351" y="124" width="120" height="60" fill="none" stroke="#0060ad" stroke-width="2" pointer-events="all"/><g fill="#0060ad" font-family="Open Sans" font-weight="bold" text-anchor="middle" font-size="11.999999999999998px"><text x="410.5" y="158.5">Model</text></g></g></svg>
|
After Width: | Height: | Size: 4.9 KiB |
4
empty/.sajt/media/static/images/svgs/mvvm.svg
Normal file
4
empty/.sajt/media/static/images/svgs/mvvm.svg
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Do not edit this file with editors other than draw.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="572px" height="63px" viewBox="-0.5 -0.5 572 63" content="<mxfile host="Electron" modified="2023-11-15T22:26:32.916Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.0.3 Chrome/114.0.5735.289 Electron/25.8.4 Safari/537.36" version="22.0.3" etag="69OR-mwMNjNfgNuLt2t0" type="device"><diagram name="Page-1" id="UDvbTf5mp8RW8-KXhH33">7Vhbb9owFP41vE65kEAfC7TbpG6rVHXrHg0xiVeTEzmmQH/97OSYxLm0bNC1qiYhYX8+5/jynRsM/Olq+1GQLPkCEeUDz4m2A3828DzXDXz1pZEdIo4blEgsWIRYBdywR2oEEV2ziOaWoATgkmU2uIA0pQtpYUQI2NhiS+D2rhmJaQu4WRDeRn+wSCYlOvZGFf6JsjgxO7vhWbmyIkYYb5InJIJNDfIvBv5UAMhytNpOKdevZ96l1LvsWd0fTNBUHqLglQoPhK/xbnguuTOXpZG6O05ByARiSAm/qNCJgHUaUW3RUbNK5gogU6CrwF9Uyh0SSdYSFLSEVE6Bgyi28R0ndIiyMcmlgHvav2Je3EMb5mx6G8JZnKrxQl2fKvUJJ3PKryFnkoG18ECFZIrRq4bAikVRcSkjcI4m9wvKgtjd4YbF5Ke++YfATGdbfIlytjOzLZN3tXFNS80qJT0xOiUZmgGL3xzWYoFQiP5PREyR8lHbC9y9b6mopLCi6mRKRFBOJHuwrROMjngvh6rnQpBdTSADlsq8ZvlaA0oAI9038YpxHp41nPHP5NWgPEGP9tjWHjmOfZ/y1VDriWN4YeMYw4ah8q1bhtSg9rgVVIRcd/j5rfCbEUkUMmdpxNK4MxgLl+1y9qbLzkFKWOkApTl7JPPCiHYrJE5ZDCaDYNYdjOcaT0CwR7VGODr83wdUoTkhi/u4yBdmtxRSuvd0bYRuLW/EHI6nrzJn3bu9U3h35QdGBJbLnB5L8fD1Muw+Uzl2pvKeS1V93tBMt+2E3Jm8C12T/lwr/Xkvkf/cDhc5NgFaHvAE3UGL7tssIpLm/0P5oFAevuFQDlvcfmd0g/1tg107YpeM88YraZouyYpx7evfMpoq/RuS5i/SGfUxckCEoMLQaRRFUyQ3VQPsGkKTWvMbOv1kHRpUo86HH2hCdM+gXU59nNvPGp6qmwvgXLnyM6Q8wUA3X6duV0/Aizt+RV7Gb6C2Nbrw0WlrW5dkm9fu1n50dG0zhaxe3MLT17buNjj0mv10cFA/3f8r4YjUe9bytK8g2ZK9r7qaZ2Shuv4JHqo4CGJXdCkRecHqO37D1dcEQ80HDiq97yHLh/6/y/JqWv3/VPJU/Y3nX/wG</diagram></mxfile>"><defs/><g><path d="M 220 30 L 130 30 L 128.24 30" fill="none" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 122.24 30 L 130.24 26 L 128.24 30 L 130.24 34 Z" fill="#0060ad" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g fill="#0060AD" font-family="Helvetica" text-anchor="middle" font-size="11px"><text x="169.95" y="25.41">Data binding</text></g><path d="M 340 15 L 441.76 15" fill="none" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 447.76 15 L 439.76 19 L 441.76 15 L 439.76 11 Z" fill="#0060ad" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g fill="#0060AD" font-family="Helvetica" text-anchor="middle" font-size="11px"><text x="395.41" y="10.41">Updates</text></g><rect x="220" y="0" width="120" height="60" fill="none" stroke="#0060ad" stroke-width="2" pointer-events="all"/><g fill="#0060ad" font-family="Open Sans" font-weight="bold" text-anchor="middle" font-size="12px"><text x="279.5" y="34.5">ViewModel</text></g><rect x="0" y="0" width="120" height="60" fill="none" stroke="#0060ad" stroke-width="2" pointer-events="all"/><g fill="#0060ad" font-family="Open Sans" font-weight="bold" text-anchor="middle" font-size="12px"><text x="59.5" y="27.5">View</text><text x="59.5" y="41.5">+ UIViewController</text></g><path d="M 450 45 L 348.24 45" fill="none" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 342.24 45 L 350.24 41 L 348.24 45 L 350.24 49 Z" fill="#0060ad" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g fill="#0060AD" font-family="Helvetica" text-anchor="middle" font-size="11px"><text x="394.5" y="40.41">Notifies</text></g><rect x="450" y="0" width="120" height="60" fill="none" stroke="#0060ad" stroke-width="2" pointer-events="all"/><g fill="#0060ad" font-family="Open Sans" font-weight="bold" text-anchor="middle" font-size="12px"><text x="509.5" y="34.5">Model</text></g></g></svg>
|
After Width: | Height: | Size: 3.9 KiB |
4
empty/.sajt/media/static/images/svgs/test-graph.svg
Normal file
4
empty/.sajt/media/static/images/svgs/test-graph.svg
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Do not edit this file with editors other than draw.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="402px" height="252px" viewBox="-0.5 -0.5 402 252" content="<mxfile host="Electron" modified="2023-10-25T22:24:22.516Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.0.3 Chrome/114.0.5735.289 Electron/25.8.4 Safari/537.36" etag="bTbxmJN1u4h5iuN82-fe" version="22.0.3" type="device"><diagram name="Page-1" id="Rsnn_ZEz_QR4m3hk7b2z">1ZfLcpswFIafxstmACV2svQtzSKddOJF2+xkOAa5QocKEUOfvhJIGGzHSWbstN14pF9Ht//jSPKATNPys6RZ8gUj4IPAi8oBmQ2CYDS80b9GqBphSPxGiCWLGqkjLNhvsKJn1YJFkPcCFSJXLOuLIQoBoeppVErc9MNWyPuzZjSGPWERUr6vfmORShr1Ohht9TtgceJm9t2GU+qC7U7yhEa46UhkPiBTiaiaUlpOgRvvnC9Nv9sXWtuFSRDqLR2eHuRG+nORLp9G5BeuHuXj+BNpRnmmvLAbtotVlXMAIm2IraJUCcYoKJ9v1YnEQkRgpvF0bRtzj5hp0dfiGpSqLF1aKNSSXrasvptOF1eu+sOOUVdmZa9W2doKhZoiR1kvj3je0KN67kmuJP6El1scvsCO4fZkjTTbfNFZK+VYyBCO2Om+UCpjUEfigpa/zhvAFPQGdT8JnCr23F8HtV9w3MZtIeuC5fwO5v4e83WyXO9x71NdMc6dtwIFWBNvacq4IfOQgdD9F1Tk52P0DFJBeZzSvqu2w6VLRHsSXdvqZpvWvgtJOik99M7EITjAYZ28xuGI6YcRnZYDmZwABdlBEYz+NovLN5yDnOtLx7iqT/LMiCHHwni2SZiCRUbro2Gjr8HzwTiB+f5N33zff6P51+cy/2rP/HGotBm7BJzvRcqbADIxTjB9W9/TJfCvmDPFUOiQJSqFaSdgzFlsGpS5kiZYKM6E9tw9Gv6FI+4kdK+GO6l1gC75yMwavp5Z7cvIUIhonrSnHbXUQr17kAdwpiyKeDcn0zI279CL5u0XXOhYnaVqhsWSw403NrKZpfKN5/WEpSkGTVE7OxvVxaot1kPdgWHY9Ph/crtF3c1t7wD+VnwHf13dvl7rts5fADL/Aw==</diagram></mxfile>"><defs/><g><path d="M 291 61 L 291 126 L 191 126 L 191 182.76" fill="none" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 191 188.76 L 187 180.76 L 191 182.76 L 195 180.76 Z" fill="#0060ad" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><rect x="231" y="1" width="120" height="60" fill="none" stroke="#0060ad" stroke-width="2" pointer-events="all"/><g fill="#0060ad" font-family="Open Sans" font-weight="bold" text-anchor="middle" font-size="12px"><text x="290.5" y="35.5">jhbj</text></g><rect x="131" y="191" width="120" height="60" fill="none" stroke="#0060ad" stroke-width="2" pointer-events="all"/><g fill="#0060ad" font-family="Open Sans" font-weight="bold" text-anchor="middle" font-size="12px"><text x="190.5" y="225.5">jhjh</text></g><path d="M 31 51 C 7 51 1 71 20.2 75 C 1 83.8 22.6 103 38.2 95 C 49 111 85 111 97 95 C 121 95 121 79 106 71 C 121 55 97 39 76 47 C 61 35 37 35 31 51 Z" fill="none" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><ellipse cx="386" cy="138.5" rx="7.5" ry="7.5" fill="none" stroke="#0060ad" stroke-width="2" pointer-events="all"/><path d="M 386 146 L 386 171 M 386 151 L 371 151 M 386 151 L 401 151 M 386 171 L 371 191 M 386 171 L 401 191" fill="none" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g fill="#0060ad" font-family="Open Sans" font-weight="bold" text-anchor="middle" font-size="12px"><text x="385.5" y="208.5">Actor</text></g><path d="M 1 151 L 71 151 L 71 176 L 81 176 L 81 166 L 101 186 L 81 206 L 81 196 L 71 196 L 71 221 L 46 221 L 46 231 L 56 231 L 36 251 L 16 231 L 26 231 L 26 221 L 1 221 Z" fill="none" stroke="#0060ad" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/></g></svg>
|
After Width: | Height: | Size: 3.4 KiB |
4
empty/.sajt/media/static/images/svgs/viper-ownership.svg
Normal file
4
empty/.sajt/media/static/images/svgs/viper-ownership.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 7.9 KiB |
9
empty/first-page.md
Normal file
9
empty/first-page.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
layout: default
|
||||
title: Content
|
||||
hidden: true
|
||||
---
|
||||
|
||||
# Content
|
||||
|
||||
there is my awasome content
|
8
empty/index.md
Normal file
8
empty/index.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
layout: default
|
||||
hidden: true
|
||||
---
|
||||
|
||||
# Welcome
|
||||
|
||||
Welcome to my website!
|
19
index.js
19
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)
|
53
markdown.js
Normal file
53
markdown.js
Normal file
|
@ -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 });
|
||||
}
|
||||
}
|
||||
}
|
1414
package-lock.json
generated
1414
package-lock.json
generated
File diff suppressed because it is too large
Load diff
19
package.json
19
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"
|
||||
}
|
||||
}
|
||||
|
|
20
project.js
Normal file
20
project.js
Normal file
|
@ -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"]
|
||||
}
|
11
serve.js
Normal file
11
serve.js
Normal file
|
@ -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}`)
|
||||
})
|
||||
}
|
239
site
239
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 = `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/styles/default.min.css">
|
||||
<meta charset="UTF-8">
|
||||
<title>${metadata.title}</title>
|
||||
<meta name="author" content="${metadata.author}">
|
||||
<meta name="date" content="${metadata.date}">
|
||||
<link rel="stylesheet" href="../.site/templates/all.css">
|
||||
</head>
|
||||
<body>
|
||||
${htmlContent}
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
// 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 <p> 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}`)
|
||||
});
|
||||
|
||||
|
|
39
ssh.js
Normal file
39
ssh.js
Normal file
|
@ -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}`)
|
||||
}
|
||||
}
|
||||
}
|
53
utils.js
Normal file
53
utils.js
Normal file
|
@ -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)
|
||||
}
|
20
watch.js
Normal file
20
watch.js
Normal file
|
@ -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}`);
|
Loading…
Add table
Add a link
Reference in a new issue