Compare commits

...

14 commits

Author SHA1 Message Date
John Shaver
49b7a59c05 Fixed some wording 2022-07-23 13:31:54 -07:00
John Shaver
3edaa49ce7 get thumbnails all in place and working 2022-07-17 14:14:19 -07:00
John Shaver
9cce6dbf0a add some javascript to make images work better 2022-07-16 23:46:23 -07:00
John Shaver
ff3beac8ff make teh thumbnails 2022-07-12 08:39:50 -07:00
John Shaver
139d80f2fe making progress 2022-07-12 08:15:33 -07:00
cce0e0d08b update delpoy location
All checks were successful
continuous-integration/drone/push Build is passing
2021-06-20 21:17:14 -07:00
400bb3eab5 add master deploy
All checks were successful
continuous-integration/drone/push Build is passing
2021-06-17 00:20:34 -07:00
7a5684daee fix recursive
All checks were successful
continuous-integration/drone/push Build is passing
2021-06-17 00:05:29 -07:00
67f7141c56 update files from list
Some checks failed
continuous-integration/drone/push Build is failing
2021-06-17 00:01:41 -07:00
901d82eb79 fix settings?
Some checks failed
continuous-integration/drone/push Build is failing
2021-06-16 23:53:07 -07:00
25b68e7621 fix yml
Some checks reported errors
continuous-integration/drone/push Build encountered an error
2021-06-16 23:37:26 -07:00
f3c782e8d7 update drone? 2021-06-16 23:35:32 -07:00
4d482c3ce4 update package.json and add package lock
Some checks reported errors
continuous-integration/drone/push Build encountered an error
2021-06-16 23:18:39 -07:00
a52b1278cb add drone config?
Some checks failed
continuous-integration/drone/push Build is failing
2021-06-16 23:15:45 -07:00
17 changed files with 889 additions and 32 deletions

69
.drone.yml Normal file
View file

@ -0,0 +1,69 @@
kind: pipeline
type: docker
name: test
trigger:
event:
- push
steps:
- name: test
image: node:lts-alpine
commands:
- npm ci
- npm test
---
kind: pipeline
type: docker
name: deploy-staging
trigger:
event:
- push
branch:
exclude:
- master
steps:
- name: deploy
image: drillster/drone-rsync
settings:
hosts:
- jshaver.net
user: deploy
key:
from_secret: deploy-key
source: ./
target: /var/www/jshaver_net/stage/${DRONE_BRANCH}/
recursive: true
args:
- "--files-from=deploy-list.txt"
---
kind: pipeline
type: docker
name: deploy-master
trigger:
branch:
- master
event:
- push
steps:
- name: deploy
image: drillster/drone-rsync
settings:
hosts:
- jshaver.net
user: deploy
key:
from_secret: deploy-key
source: ./
target: /var/www/jshaver_net/
recursive: true
args:
- "--files-from=deploy-list.txt"

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
node_modules
images/thumbnails

View file

@ -4,8 +4,8 @@
position: relative; position: relative;
justify-content: space-between; justify-content: space-between;
flex-wrap: wrap; flex-wrap: wrap;
max-width: unset; width: unset;
width: 90vw; max-width: unset;
margin-left: -0.5rem; margin-left: -0.5rem;
margin-right: -0.5rem; margin-right: -0.5rem;
margin-top: 0.8rem; margin-top: 0.8rem;
@ -21,8 +21,7 @@
img {} img {}
.project-image > img { .project-image > img {
max-width: 90%; margin: 0 0.5rem;
margin: 0.5rem;
} }
.social-links img { .social-links img {

View file

@ -104,3 +104,43 @@ section {
.project-info { .project-info {
margin: 1.5em 0 5em 0; margin: 1.5em 0 5em 0;
} }
.clickable {
cursor: pointer;
}
.close-x {
font-size: 25px;
text-align: end;
padding: 10px 10px 0;
}
#image-modal-wrapper {
position: fixed;
background: rgba(0,0,0,0.25);
width: 100%;
height: 100%;
left: 0;
top: 0;
}
#image-modal-flex {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
#image-modal {
flex-grow: 0;
max-width: 90vh;
background: #FFF;
border-radius: 4px;
}
#image-modal-contents img {
box-sizing: border-box;
padding: 10px 25px 25px;
max-width: 100%;
}

4
deploy-list.txt Normal file
View file

@ -0,0 +1,4 @@
css/
images/
js/
index.html

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

BIN
images/skillabi-1-login.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

BIN
images/skillabi-2.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 KiB

BIN
images/skillabi-3.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

BIN
images/skills-match-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View file

@ -3,7 +3,7 @@
<link rel="stylesheet" href="css/main.css" /> <link rel="stylesheet" href="css/main.css" />
<link rel="stylesheet" media="screen and (max-width: 700px)" href="css/700.css" /> <link rel="stylesheet" media="screen and (max-width: 700px)" href="css/700.css" />
<link href="https://fonts.googleapis.com/css?family=Roboto:400,400i,500,500i" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto:400,400i,500,500i" rel="stylesheet">
<title>Javascipt Developer - Portfolio</title> <title>Fullstack Developer - Portfolio</title>
</head> </head>
<body> <body>
<div class="flex-container"> <div class="flex-container">
@ -33,29 +33,110 @@
<section class="section about"> <section class="section about">
<h2>About Me</h2> <h2>About Me</h2>
<p class="attention">I'm a full-stack engineer with experience building <p class="attention">I'm a full-stack engineer with experience building
and deploying web based applications from the ground up as well as and deploying web based applications, building out CI/CD pipelines and
debugging and maintaining legacy systems. I am looking for a remote maintaining legacy applications. I am looking for a remote position
full-stack/frontend position with a team that embraces remote work.</p> building web based software with a team that embraces remote work.</p>
<p>I have been working with websites and code since I was a kid and then <p>I have been working with websites and code since I was a kid and then
worked 7 years in technical support where I gained a solid worked 7 years in technical support where I gained a solid understanding
understanding of the web and how it works under the hood. I have spent of the web and how it works under the hood. I have spent the last 10 years
the last 4 years designing, building, deploying and maintaining designing, building, deploying and maintaining javascript and typescript
javascript applications. I've worked with iOS, PHP, NodeJS, and applications. I've worked with NodeJS, React, and Serverless.js. I
React/Redux. I enjoy learning better ways to do things, solving enjoy learning better ways to do things, solving difficult problems and
difficult problems and building software that assists my clients/users building software that helps people. I live in Moscow Idaho and my
in achieving success. I live in Hayden Idaho and my hobbies include hobbies include Devops, listening` to podcasts, playing ukulele and,
Devops, listening to podcasts, playing ukulele and, especially, especially, spending time with my wife and 4 kids.</p>
spending time with my wife and 3 kids.</p>
</section> </section>
<section class="section projects"> <section class="section projects">
<h2>Recent Software Projects</h2> <h2>Recent Software Projects</h2>
<h3>Dashdrop</h3> <h3><a href="https://www.economicmodeling.com/skillabi/">Skillabi</a></h3>
<div class="project"> <div class="project">
<div class="project-image"> <div class="project-image">
<img class="main-image" src="images/dashdrop-1.png"/> <img class="main-image" src="images/thumbnails/th_skillabi-1-login.png"/>
<img class="main-image" src="images/dashdrop-2.png"/> <img class="main-image" src="images/thumbnails/th_skillabi-2.gif"/>
<img class="main-image" src="images/dashdrop-3.png"/> <img class="main-image" src="images/thumbnails/th_skillabi-3.webp"/>
<img class="main-image" src="images/thumbnails/th_curricular-skills-api.png"/>
</div>
<div class="project-info">
<h4>Project Goals</h4>
<p>Skillabi is a tool to help Higher Education institutions to find
skills that are relivant to their curriculum and in-demand in the
market place so they can adjust they're curriculum to be more
relevant to the developing job market. Skills are parsed from
course data and then compared with skills job postings data for
relevant occupations.</p>
<h4>My Contributions</h4>
<p>I worked on a 2-3 man team to build a prototype using netlify. We then
itterated on it in 3 phases. The prototype was successful enough
that customers requested to pay to use it (although it chock full
of technical debt on the inside.) When it came time to build a
production version, I took over as the technical lead on the
project. This included designing a new version of the backend APIs
and leading the reimplementation of the frontend.</p>
<p>The new APIs for storing curricular data and user profiles
needed to be secure, easy to use, well tested, well documented,
scalable and reliable. We ensured that security was implemeted in
the back end first. We used cognito tokens and JWT claims to scope
user access by role. We designed api search queries for the a
curricular data that ensured the API could be easily expanded and
would be consistant across endpoints, while still being powerful
enought to do all the searching/filtering that would be needed in
the frontend. We implemented the API on AWS serverless lambdas for
scalability and reliability and used typescript on serverless.js
for ease of development.</p>
<p>The new frontend was developed with react, written in typescript
and served via cloudfront and s3 for scalabilty, reliability and
simplicity. It also had to meet the accessiblity requirements of US
and UK educational institutions. I was tasked with implementing
some of the more complicated problems, including realtime
highlighting of skills within a text area as users type (The
parsing of the skills was handled by an external API), and
identifying boilerplate text accross many courses in a curriculum
for parsing. </p>
<h4>Technologies Used</h4>
<p>Typescript, Terraform, Gitlab CI, Fugue, OpenId/OAuth, React,
Accessibility, Serverless.js, react-query, JWT, KONG</p>
</div>
</div>
<h3>Skillsmatch</h3>
<div class="project">
<div class="project-image">
<img class="main-image" src="images/thumbnails/th_skills-match-img-1.webp"/>
<img class="main-image" src="images/thumbnails/th_skills-match-2.png"/>
<img class="main-image" src="images/thumbnails/th_skills-match-img-3.webp"/>
</div>
<div class="project-info">
<h4>Project Goals</h4>
<p>Skillsmtch is an web based app that schools can provide to their
students and potential student who are coming back to school after
some time in the workplace. Skillsmatch helps these adult learners
catalogue the skills they already have so they can see what skills
they could then learn to make help with either making themselves
more marketable or shifting careers. It then helps them identify
courses or degrees that could help them to learn and demonstrate
those skills to potential employers.</p>
<h4>My Contributions</h4>
<p>I worked with my team as a newly hired developer at the company
to quickly rebuild the already developed prototype. We build out
out necessary APIs using serverless.js/Mongodb and frontend in
Javascript with React/Redux. I wrote code for, reviewed and QA'd
tickets. I particularly enjoyed teaching new developers and interns
as they were hired, implementing API tests on our new APIs and
building out dev ops systems to automatically deploy to AWS.</p>
<h4>Technologies Used</h4>
<p>React, Cypress, AWS Elastic Beanstalk, Serverless.js,
Accessibility, Redux, Docker, Codeship CI</p>
</div>
</div>
<h3>Dash Drop</h3>
<div class="project">
<div class="project-image">
<img class="main-image" src="images/thumbnails/th_dashdrop-1.png"/>
<img class="main-image" src="images/thumbnails/th_dashdrop-2.png"/>
<img class="main-image" src="images/thumbnails/th_dashdrop-3.png"/>
</div> </div>
<div class="project-info"> <div class="project-info">
<h4>Project Goals</h4> <h4>Project Goals</h4>
@ -71,13 +152,12 @@
Javascript, where needed, to change the structure of the Javascript, where needed, to change the structure of the
interface.</p> interface.</p>
<h4>Technologies Used</h4> <h4>Technologies Used</h4>
<p>CSS and some JQuery</p> <p>HTML, CSS, Javascript and some JQuery</p> </div>
</div>
</div> </div>
<h3>NewVistas Website Platform</h3> <h3>NewVistas Website Platform</h3>
<div class="project"> <div class="project">
<div class="project-image"> <div class="project-image">
<img class="main-image" src="images/newvistas.jpg"/> <img class="main-image" src="images/thumbnails/th_newvistas.jpg"/>
</div> </div>
<div class="project-info"> <div class="project-info">
<h4>Project Goals</h4> <h4>Project Goals</h4>
@ -130,8 +210,8 @@
<h3>Payzoom Econosystem Platform</h3> <h3>Payzoom Econosystem Platform</h3>
<div class="project"> <div class="project">
<div class="project-image"> <div class="project-image">
<img alt="The Payzoom Logo" src="images/PayZoom_logo.png"/> <img alt="The Payzoom Logo" src="images/thumbnails/th_PayZoom_logo.png"/>
<img class="main-image" alt="Payzoom Software Demo" src="images/payzoom.png"/> <img class="main-image" alt="Payzoom Software Demo" src="images/thumbnails/th_payzoom.png"/>
</div> </div>
<div class="project-info"> <div class="project-info">
<h4>Project Goal</h4> <h4>Project Goal</h4>
@ -172,8 +252,8 @@
<h3>Novatek Native Wrapper App</h3> <h3>Novatek Native Wrapper App</h3>
<div class="project"> <div class="project">
<div class="project-image"> <div class="project-image">
<img class="main-image" alt="Workaids App Icon" src="images/icon_work_aids.png" /> <img class="main-image" alt="Workaids App Icon" src="images/thumbnails/th_icon_work_aids.png" />
<img alt="Workaids Login Screen" src="images/workaids_login2.png" /> <img alt="Workaids Login Screen" src="images/thumbnails/th_workaids_login2.png" />
</div> </div>
<div class="project-info"> <div class="project-info">
<h4>Project Goals</h4> <h4>Project Goals</h4>
@ -184,7 +264,7 @@
built to wrap the current web interface and allow built to wrap the current web interface and allow
reusing the existing web based code as much as reusing the existing web based code as much as
possible.</p> possible.</p>
<h4>My Contrinbutions</h4> <h4>My Contributions</h4>
<p>Initially I helped write many of the api calls for <p>Initially I helped write many of the api calls for
the js library the web app used to communicate through the js library the web app used to communicate through
the webFrame to the native code. Later I helped out the webFrame to the native code. Later I helped out
@ -209,4 +289,13 @@
</section> </section>
</article> </article>
</div> </div>
<div id="image-modal-wrapper" hidden>
<div id="image-modal-flex">
<div id="image-modal">
<div class="close-x clickable" aria-label="click to close modal">&#xd7;</div>
<div id="image-modal-contents" />
</div>
</div>
</div>
<script src="./js/image-thumbnails.js"></script>
</body> </body>

51
js/image-thumbnails.js Normal file
View file

@ -0,0 +1,51 @@
'use srict';
(function() {
const imageModalWrapper = document.querySelector('#image-modal-wrapper');
const imageModalFlex = document.querySelector('#image-modal-flex');
const imageModal = document.querySelector('#image-modal');
const imageModalContents = document.querySelector('#image-modal-contents');
imageModal.querySelector('.close-x').addEventListener('click', function(e) {
e.stopPropagation();
e.preventDefault();
imageModalWrapper.hidden = true;
});
imageModalFlex.addEventListener('click', function(e) {
if(e.target === imageModalFlex) {
e.stopPropagation();
e.preventDefault();
imageModalWrapper.hidden = true;
}
});
window.addEventListener('keydown', function(e) {
const modalCloseKeys = ['escape', 'tab']
console.log("e.key: ", e.key);
if(!imageModalWrapper.hidden) {
if(modalCloseKeys.includes(e.key.toLowerCase())) {
imageModalWrapper.hidden = true;
}
}
});
const images = document.querySelectorAll('img');
images.forEach(function(img) {
const name = img.src.split('/').pop();
if(name.match(/^th_/)) {
img.classList.add('clickable');
img.addEventListener('click', function(e) {
e.stopPropagation();
e.preventDefault();
imageModalWrapper.hidden = undefined;
const fullImage = document.createElement('img');
fullImage.src = `./images/${name.replace(/^th_/, '')}`;
imageModalContents.replaceChildren(fullImage);
});
}
});
})();

581
package-lock.json generated Normal file
View file

@ -0,0 +1,581 @@
{
"name": "portfolio",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "1.0.0",
"license": "UNLICENSED",
"devDependencies": {
"http-server": "^0.12.3"
}
},
"node_modules/async": {
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
"integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
"dev": true,
"dependencies": {
"lodash": "^4.17.14"
}
},
"node_modules/basic-auth": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz",
"integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=",
"dev": true,
"engines": {
"node": ">= 0.6"
}
},
"node_modules/call-bind": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/colors": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
"integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
"dev": true,
"engines": {
"node": ">=0.1.90"
}
},
"node_modules/corser": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz",
"integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=",
"dev": true,
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
"dependencies": {
"ms": "^2.1.1"
}
},
"node_modules/ecstatic": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz",
"integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==",
"dev": true,
"dependencies": {
"he": "^1.1.1",
"mime": "^1.6.0",
"minimist": "^1.1.0",
"url-join": "^2.0.5"
},
"bin": {
"ecstatic": "lib/ecstatic.js"
}
},
"node_modules/eventemitter3": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
"dev": true
},
"node_modules/follow-redirects": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==",
"dev": true,
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
},
"node_modules/get-intrinsic": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
"integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.1"
},
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/has-symbols": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
"integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
"dev": true,
"bin": {
"he": "bin/he"
}
},
"node_modules/http-proxy": {
"version": "1.18.1",
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
"integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
"dev": true,
"dependencies": {
"eventemitter3": "^4.0.0",
"follow-redirects": "^1.0.0",
"requires-port": "^1.0.0"
},
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/http-server": {
"version": "0.12.3",
"resolved": "https://registry.npmjs.org/http-server/-/http-server-0.12.3.tgz",
"integrity": "sha512-be0dKG6pni92bRjq0kvExtj/NrrAd28/8fCXkaI/4piTwQMSDSLMhWyW0NI1V+DBI3aa1HMlQu46/HjVLfmugA==",
"dev": true,
"dependencies": {
"basic-auth": "^1.0.3",
"colors": "^1.4.0",
"corser": "^2.0.1",
"ecstatic": "^3.3.2",
"http-proxy": "^1.18.0",
"minimist": "^1.2.5",
"opener": "^1.5.1",
"portfinder": "^1.0.25",
"secure-compare": "3.0.1",
"union": "~0.5.0"
},
"bin": {
"hs": "bin/http-server",
"http-server": "bin/http-server"
},
"engines": {
"node": ">=6"
}
},
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"node_modules/mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
"dev": true,
"bin": {
"mime": "cli.js"
},
"engines": {
"node": ">=4"
}
},
"node_modules/minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
"dev": true
},
"node_modules/mkdirp": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
"dev": true,
"dependencies": {
"minimist": "^1.2.5"
},
"bin": {
"mkdirp": "bin/cmd.js"
}
},
"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==",
"dev": true
},
"node_modules/object-inspect": {
"version": "1.10.3",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz",
"integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/opener": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
"integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
"dev": true,
"bin": {
"opener": "bin/opener-bin.js"
}
},
"node_modules/portfinder": {
"version": "1.0.28",
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz",
"integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==",
"dev": true,
"dependencies": {
"async": "^2.6.2",
"debug": "^3.1.1",
"mkdirp": "^0.5.5"
},
"engines": {
"node": ">= 0.12.0"
}
},
"node_modules/qs": {
"version": "6.10.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz",
"integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==",
"dev": true,
"dependencies": {
"side-channel": "^1.0.4"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/requires-port": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
"dev": true
},
"node_modules/secure-compare": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz",
"integrity": "sha1-8aAymzCLIh+uN7mXTz1XjQypmeM=",
"dev": true
},
"node_modules/side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.0",
"get-intrinsic": "^1.0.2",
"object-inspect": "^1.9.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/union": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz",
"integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==",
"dev": true,
"dependencies": {
"qs": "^6.4.0"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/url-join": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz",
"integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=",
"dev": true
}
},
"dependencies": {
"async": {
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
"integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
"dev": true,
"requires": {
"lodash": "^4.17.14"
}
},
"basic-auth": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz",
"integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=",
"dev": true
},
"call-bind": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
"dev": true,
"requires": {
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2"
}
},
"colors": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
"integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
"dev": true
},
"corser": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz",
"integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=",
"dev": true
},
"debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"ecstatic": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz",
"integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==",
"dev": true,
"requires": {
"he": "^1.1.1",
"mime": "^1.6.0",
"minimist": "^1.1.0",
"url-join": "^2.0.5"
}
},
"eventemitter3": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
"dev": true
},
"follow-redirects": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==",
"dev": true
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
},
"get-intrinsic": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
"integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
"dev": true,
"requires": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1"
}
},
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"dev": true,
"requires": {
"function-bind": "^1.1.1"
}
},
"has-symbols": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
"integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==",
"dev": true
},
"he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
"dev": true
},
"http-proxy": {
"version": "1.18.1",
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
"integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
"dev": true,
"requires": {
"eventemitter3": "^4.0.0",
"follow-redirects": "^1.0.0",
"requires-port": "^1.0.0"
}
},
"http-server": {
"version": "0.12.3",
"resolved": "https://registry.npmjs.org/http-server/-/http-server-0.12.3.tgz",
"integrity": "sha512-be0dKG6pni92bRjq0kvExtj/NrrAd28/8fCXkaI/4piTwQMSDSLMhWyW0NI1V+DBI3aa1HMlQu46/HjVLfmugA==",
"dev": true,
"requires": {
"basic-auth": "^1.0.3",
"colors": "^1.4.0",
"corser": "^2.0.1",
"ecstatic": "^3.3.2",
"http-proxy": "^1.18.0",
"minimist": "^1.2.5",
"opener": "^1.5.1",
"portfinder": "^1.0.25",
"secure-compare": "3.0.1",
"union": "~0.5.0"
}
},
"lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
"dev": true
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
"dev": true
},
"mkdirp": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
"dev": true,
"requires": {
"minimist": "^1.2.5"
}
},
"ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true
},
"object-inspect": {
"version": "1.10.3",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz",
"integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==",
"dev": true
},
"opener": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
"integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
"dev": true
},
"portfinder": {
"version": "1.0.28",
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz",
"integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==",
"dev": true,
"requires": {
"async": "^2.6.2",
"debug": "^3.1.1",
"mkdirp": "^0.5.5"
}
},
"qs": {
"version": "6.10.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz",
"integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==",
"dev": true,
"requires": {
"side-channel": "^1.0.4"
}
},
"requires-port": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
"dev": true
},
"secure-compare": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz",
"integrity": "sha1-8aAymzCLIh+uN7mXTz1XjQypmeM=",
"dev": true
},
"side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
"dev": true,
"requires": {
"call-bind": "^1.0.0",
"get-intrinsic": "^1.0.2",
"object-inspect": "^1.9.0"
}
},
"union": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz",
"integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==",
"dev": true,
"requires": {
"qs": "^6.4.0"
}
},
"url-join": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz",
"integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=",
"dev": true
}
}
}

View file

@ -4,9 +4,13 @@
"description": "My portfolio website", "description": "My portfolio website",
"main": "index.html", "main": "index.html",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo 'no tests yet.... so... pass?'",
"push-to-live": "rsync -rv --progress ./ do:/var/www/jshaver_net" "start": "http-server ./",
"thumbs": "./scripts/process-images.sh"
}, },
"author": "john@jshaver.net", "author": "john@jshaver.net",
"license": "UNLICENSED" "license": "UNLICENSED",
"devDependencies": {
"http-server": "^0.12.3"
}
} }

17
scripts/process-images.sh Executable file
View file

@ -0,0 +1,17 @@
#!/bin/bash
IMAGES_DIR="./images"
WIDTH=320
for f in ./images/*
do
case "$f" in
*.jpeg|*.jpg|*.png|*.webp|*.gif)
echo "Processing $f"
convert $f -resize $WIDTH\> ./images/thumbnails/th_`basename $f`
;;
*)
echo "Ignoring $f"
;;
esac
done