Revert "Revert "Migrate Postwoman to Nuxt.js (full Vue and SCSS support)""

This commit is contained in:
Liyas Thomas
2019-08-24 22:09:29 +05:30
committed by GitHub
parent dbcd7442fe
commit b027eeb846
39 changed files with 12054 additions and 816 deletions

92
.gitignore vendored
View File

@@ -1 +1,91 @@
node_modules # Created by .ignore support plugin (hsz.mobi)
### Node template
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# Nuxt generate
dist
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless
# IDE / Editor
.idea
.editorconfig
# Service worker
sw.*
# Mac OSX
.DS_Store
# Vim swap files
*.swp

View File

@@ -7,9 +7,28 @@
language: node_js language: node_js
node_js: node_js:
- "node" - "8"
notifications:
webhooks: https://www.travisbuddy.com cache:
env: directories:
- MY_VAR=EverythignIsAwesome - "node_modules"
- NODE_ENV=TEST
branches:
only:
- master
install:
- npm install
- npm run generate
script:
- echo "Skipping tests"
deploy:
provider: pages
skip-cleanup: true
github-token: $GITHUB_ACCESS_TOKEN # Set in travis-ci.org dashboard, marked secure https://docs.travis-ci.com/user/deployment/pages/#Setting-the-GitHub-token
target-branch: gh-pages
local-dir: dist
on:
branch: master

View File

@@ -1,88 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset='utf-8'>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, shrink-to-fit=no">
<title>Postwoman - API request builder</title>
<meta name="description" content="The Postwoman API request builder helps you create your requests faster, saving you precious time on your development.">
<link rel="icon" href="favicon.ico">
<meta itemprop="name" content="Postwoman - API request builder">
<meta itemprop="description" content="The Postwoman API request builder helps you create your requests faster, saving you precious time on your development.">
<meta itemprop="image" content="icons/icon-192x192.png">
<!-- See https://goo.gl/OOhYW5 -->
<link rel="manifest" href="manifest.json">
<!-- See https://goo.gl/qRE0vM -->
<meta name="theme-color" content="#121212">
<!-- Add to homescreen for Chrome on Android. Fallback for manifest.json -->
<meta name="mobile-web-app-capable" content="yes">
<meta name="application-name" content="Postwoman - API request builder">
<!-- Add to homescreen for Safari on iOS -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="Postwoman - API request builder">
<!-- Homescreen icons -->
<link rel="apple-touch-icon" href="icons/icon-48x48.png">
<link rel="apple-touch-icon" sizes="72x72" href="icons/icon-72x72.png">
<link rel="apple-touch-icon" sizes="96x96" href="icons/icon-96x96.png">
<link rel="apple-touch-icon" sizes="144x144" href="icons/icon-144x144.png">
<link rel="apple-touch-icon" sizes="192x192" href="icons/icon-192x192.png">
<!-- Tile icon for Windows 8 (144x144 + tile color) -->
<meta name="msapplication-TileImage" content="icons/icon-144x144.png">
<meta name="msapplication-TileColor" content="#121212">
<meta name="msapplication-tap-highlight" content="no">
<!-- OpenGraph -->
<meta property="og:site_name" content="Postwoman - API request builder">
<meta property="og:url" content="https://liyasthomas.github.io/postwoman">
<meta property="og:type" content="website">
<meta property="og:title" content="Postwoman - API request builder">
<meta property="og:description" content="API request builder">
<meta property="og:image" content="icons/icon-144x144.png">
<!-- Twitter -->
<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="@liyasthomas">
<meta name="twitter:creator" content="@liyasthomas">
<meta name="twitter:url" content="https://liyasthomas.github.io/postwoman">
<meta name="twitter:title" content="Postwoman - API request builder">
<meta name="twitter:description" content="API request builder">
<meta name="twitter:image" content="icons/icon-144x144.png">
<!-- Web Fonts -->
<link href="https://fonts.googleapis.com/css?family=Poppins:500,700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('sw.js').then(function(registration) {
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}).catch(function(err) {
console.log('ServiceWorker registration failed: ', err);
});
});
}
</script>
</head>
<body>
<main id="app">
<header>
<div>
<a href="index.html">
<h1 class="logo"><img src="icons/logo.svg" alt="" style="height: 24px; margin-right: 16px">Postwoman</h1>
</a>
<h3>API request builder</h3>
</div>
</header>
<h1>404 - Page not found</h1>
<p><a href="index.html"><button>Go Home</button></a></p>
<footer>
<a href="https://github.com/liyasthomas/postwoman" target="_blank"><img src="icons/github.svg" alt="" style="margin-right: 16px">GitHub</a>
<button id="installPWA" onclick="installPWA()">
Install PWA
</button>
</footer>
</main>
</body>
</html>

View File

@@ -2,27 +2,27 @@
When I wrote this, only God and I understood what I was doing. Now, only God knows. When I wrote this, only God and I understood what I was doing. Now, only God knows.
``` ```
<div align="center"> <div align="center">
<a href="https://liyas-thomas.firebaseapp.com"><img src="https://raw.githubusercontent.com/liyasthomas/templates/master/assets/logo.gif" alt="Liyas Thomas" width="200"></a> <a href="https://liyas-thomas.firebaseapp.com"><img src="https://raw.githubusercontent.com/liyasthomas/templates/master/assets/logo.gif" alt="Liyas Thomas" width="200"></a>
<br> <br>
<h1>Liyas Thomas</h1> <h1>Liyas Thomas</h1>
<sub>Built with ❤︎ by <sub>Built with ❤︎ by
<a href="https://github.com/liyasthomas">liyasthomas</a> and <a href="https://github.com/liyasthomas">liyasthomas</a> and
<a href="https://github.com/liyasthomas/postwoman/graphs/contributors">contributors</a> <a href="https://github.com/liyasthomas/postwoman/graphs/contributors">contributors</a>
</sub> </sub>
</div> </div>
--- ---
[![Build Status](https://travis-ci.org/liyasthomas/postwoman.svg?branch=master)](https://travis-ci.org/liyasthomas/postwoman) [![GitHub release](https://img.shields.io/github/release/liyasthomas/postwoman/all.svg)](https://github.com/liyasthomas/postwoman/releases/latest) [![repo size](https://img.shields.io/github/repo-size/liyasthomas/postwoman.svg)](https://github.com/liyasthomas/postwoman/archive/master.zip) [![license](https://img.shields.io/github/license/liyasthomas/postwoman.svg)](https://github.com/liyasthomas/postwoman/blob/master/LICENSE) [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/liyasthomas/postwoman/issues) [![Website](https://img.shields.io/website-up-down-green-red/https/shields.io.svg?label=website)](https://liyas-thomas.firebaseapp.com) [![Donate](https://img.shields.io/badge/$-donate-ff69b4.svg)](https://www.paypal.me/liyascthomas) [![Buy me a coffee](https://img.shields.io/badge/$-BuyMeACoffee-orange.svg)](https://www.buymeacoffee.com/liyasthomas) [![Build Status](https://travis-ci.org/liyasthomas/postwoman.svg?branch=master)](https://travis-ci.org/liyasthomas/postwoman) [![GitHub release](https://img.shields.io/github/release/liyasthomas/postwoman/all.svg)](https://github.com/liyasthomas/postwoman/releases/latest) [![repo size](https://img.shields.io/github/repo-size/liyasthomas/postwoman.svg)](https://github.com/liyasthomas/postwoman/archive/master.zip) [![license](https://img.shields.io/github/license/liyasthomas/postwoman.svg)](https://github.com/liyasthomas/postwoman/blob/master/LICENSE) [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/liyasthomas/postwoman/issues) [![Website](https://img.shields.io/website-up-down-green-red/https/shields.io.svg?label=website)](https://liyas-thomas.firebaseapp.com) [![Donate](https://img.shields.io/badge/$-donate-ff69b4.svg)](https://www.paypal.me/liyascthomas) [![Buy me a coffee](https://img.shields.io/badge/$-BuyMeACoffee-orange.svg)](https://www.buymeacoffee.com/liyasthomas)
# <img src="icons/icon-48x48.png" alt="postwoman" width="32"> Postwoman # <img src="static/icon.png" alt="postwoman" width="32"> Postwoman
### 👽 API request builder by [Liyas Thomas](https://github.com/liyasthomas) ### 👽 API request builder by [Liyas Thomas](https://github.com/liyasthomas)
<div align="center"> <div align="center">
<br> <br>
<img src="icons/screely.png" alt="postwoman" width="100%"> <img src="static/screely.png" alt="postwoman" width="100%">
<img src="icons/screely2.png" alt="postwoman" width="100%"> <img src="static/screely2.png" alt="postwoman" width="100%">
<br> <br>
</div> </div>
@@ -58,15 +58,25 @@ You're done!
* HTML - For the web framework * HTML - For the web framework
* CSS - For styling components * CSS - For styling components
* JavaScript - For magic! * JavaScript - For magic!
* [Vue](https://vuejs.org/) - To add to the JavaScript magic!
* [Nuxt](https://nuxtjs.org/) - To add to the Vue magic! <!-- (Nuxt helps create the PWA and single page application.) -->
--- ---
## Developing ## Developing
1. [Clone this repo](https://help.github.com/en/articles/cloning-a-repository) with git. 1. [Clone this repo](https://help.github.com/en/articles/cloning-a-repository) with git.
1. Install dependencies by running `npm install` within the `postwoman` directory. 1. Install dependencies by running `npm install` within the directory that you cloned (probably `postwoman`).
1. Start the development server with `npm start`. 1. Start the development server with `npm run dev`.
1. Open development site by going to [http://localhost:8080](http://localhost:8080) in your browser. 1. Open development site by going to [http://localhost:3000](http://localhost:3000) in your browser.
---
## Releasing
1. [Clone this repo](https://help.github.com/en/articles/cloning-a-repository) with git.
1. Install dependencies by running `npm install` within the directory that you cloned (probably `postwoman`).
1. Build the release files with `npm run build`.
1. Find the built project in `./dist`.
--- ---

7
assets/README.md Normal file
View File

@@ -0,0 +1,7 @@
# ASSETS
**This directory is not required, you can delete it if you don't want to use it.**
This directory contains your un-compiled assets such as LESS, SASS, or JavaScript.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#webpacked).

2
assets/css/fonts.scss Normal file
View File

@@ -0,0 +1,2 @@
// Poppins (Google Fonts)
@import url("https://fonts.googleapis.com/css?family=Poppins:500,700&display=swap");

View File

@@ -70,13 +70,15 @@ footer {
justify-content: space-between; justify-content: space-between;
} }
.logo { body.sticky-footer footer {
color: var(--ac-color); position: fixed;
bottom: 0;
left: 0;
right: 0;
} }
main { .logo {
margin: 0 auto; color: var(--ac-color);
max-width: 1200px;
} }
button { button {
@@ -213,3 +215,7 @@ ol li {
display: flex; display: flex;
} }
} }
#installPWA {
display: none;
}

54
assets/js/pwa.js Normal file
View File

@@ -0,0 +1,54 @@
export default () => {
//*** Determine whether or not the PWA has been installed. ***//
// Step 1: Check local storage
let pwaInstalled = localStorage.getItem('pwaInstalled') === 'yes';
// Step 2: Check if the display-mode is standalone. (Only permitted for PWAs.)
if (!pwaInstalled && window.matchMedia('(display-mode: standalone)').matches) {
localStorage.setItem('pwaInstalled', 'yes');
pwaInstalled = true;
}
// Step 3: Check if the navigator is in standalone mode. (Again, only permitted for PWAs.)
if (!pwaInstalled && window.navigator.standalone === true) {
localStorage.setItem('pwaInstalled', 'yes');
pwaInstalled = true;
}
//*** If the PWA has not been installed, show the install PWA prompt.. ***//
let deferredPrompt = null;
window.addEventListener('beforeinstallprompt', (event) => {
deferredPrompt = event;
// Show the install button if the prompt appeared.
if (!pwaInstalled) {
document.querySelector('#installPWA').style.display = 'block';
}
});
// When the app is installed, remove install prompts.
window.addEventListener('appinstalled', (event) => {
localStorage.setItem('pwaInstalled', 'yes');
pwaInstalled = true;
document.getElementById('installPWA').style.display = 'none';
});
// When the app is uninstalled, add the prompts back
return async () => {
if (deferredPrompt) {
deferredPrompt.prompt();
let outcome = await deferredPrompt.userChoice;
if (outcome === 'accepted') {
console.log('Postwoman was installed successfully.')
} else {
console.log('Postwoman could not be installed. (Installation rejected by user.)')
}
deferredPrompt = null;
}
};
};

7
components/README.md Normal file
View File

@@ -0,0 +1,7 @@
# COMPONENTS
**This directory is not required, you can delete it if you don't want to use it.**
The components directory contains your Vue.js Components.
_Nuxt.js doesn't supercharge these components._

View File

@@ -1,319 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset='utf-8'>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, shrink-to-fit=no">
<title>Postwoman - API request builder</title>
<meta name="description" content="The Postwoman API request builder helps you create your requests faster, saving you precious time on your development.">
<link rel="icon" href="favicon.ico">
<meta itemprop="name" content="Postwoman - API request builder">
<meta itemprop="description" content="The Postwoman API request builder helps you create your requests faster, saving you precious time on your development.">
<meta itemprop="image" content="icons/icon-192x192.png">
<!-- See https://goo.gl/OOhYW5 -->
<link rel="manifest" href="manifest.json">
<!-- See https://goo.gl/qRE0vM -->
<meta name="theme-color" content="#121212">
<!-- Add to homescreen for Chrome on Android. Fallback for manifest.json -->
<meta name="mobile-web-app-capable" content="yes">
<meta name="application-name" content="Postwoman - API request builder">
<!-- Add to homescreen for Safari on iOS -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="Postwoman - API request builder">
<!-- Homescreen icons -->
<link rel="apple-touch-icon" href="icons/icon-48x48.png">
<link rel="apple-touch-icon" sizes="72x72" href="icons/icon-72x72.png">
<link rel="apple-touch-icon" sizes="96x96" href="icons/icon-96x96.png">
<link rel="apple-touch-icon" sizes="144x144" href="icons/icon-144x144.png">
<link rel="apple-touch-icon" sizes="192x192" href="icons/icon-192x192.png">
<!-- Tile icon for Windows 8 (144x144 + tile color) -->
<meta name="msapplication-TileImage" content="icons/icon-144x144.png">
<meta name="msapplication-TileColor" content="#121212">
<meta name="msapplication-tap-highlight" content="no">
<!-- OpenGraph -->
<meta property="og:site_name" content="Postwoman - API request builder">
<meta property="og:url" content="https://liyasthomas.github.io/postwoman">
<meta property="og:type" content="website">
<meta property="og:title" content="Postwoman - API request builder">
<meta property="og:description" content="API request builder">
<meta property="og:image" content="icons/icon-144x144.png">
<!-- Twitter -->
<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="@liyasthomas">
<meta name="twitter:creator" content="@liyasthomas">
<meta name="twitter:url" content="https://liyasthomas.github.io/postwoman">
<meta name="twitter:title" content="Postwoman - API request builder">
<meta name="twitter:description" content="API request builder">
<meta name="twitter:image" content="icons/icon-144x144.png">
<!-- Web Fonts -->
<link href="https://fonts.googleapis.com/css?family=Poppins:500,700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('sw.js').then(function(registration) {
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}).catch(function(err) {
console.log('ServiceWorker registration failed: ', err);
});
});
}
</script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js'></script>
</head>
<body>
<main id="app">
<header>
<div>
<a href="">
<h1 class="logo"><img src="icons/logo.svg" alt="" style="height: 24px; margin-right: 16px">Postwoman</h1>
</a>
<h3>API request builder</h3>
</div>
</header>
<fieldset class="request" ref="request">
<legend v-on:click="collapse">Request ↕</legend>
<div class="collapsible">
<ul>
<li>
<label for="method">Method</label>
<select v-model="method">
<option>GET</option>
<option>POST</option>
<option>PUT</option>
<option>DELETE</option>
<option>OPTIONS</option>
</select>
</li>
<li>
<label for="url">URL</label>
<input type="url" v-bind:class="{ error: urlNotValid }" v-model="url" v-on:keyup.enter="sendRequest">
</li>
<li>
<label for="path">Path</label>
<input v-model="path" v-on:keyup.enter="sendRequest">
</li>
<li>
<label for="action">&nbsp;</label>
<button v-bind:class="{ disabled: urlNotValid }" name="action" @click="sendRequest">Send</button>
</li>
</ul>
</div>
</fieldset>
<fieldset class="reqbody" v-if="method === 'POST' || method === 'PUT'">
<legend v-on:click="collapse">Request Body ↕</legend>
<div class="collapsible">
<ul>
<li>
<label>Content Type</label>
<select v-model="contentType">
<option>application/json</option>
<option>www-form/urlencoded</option>
</select>
</li>
</ul>
<ol v-for="(param, index) in bodyParams">
<li>
<label :for="'bparam'+index">Key {{index + 1}}</label>
<input :name="'bparam'+index" v-model="param.key">
</li>
<li>
<label :for="'bvalue'+index">Value {{index + 1}}</label>
<input :name="'bvalue'+index" v-model="param.value">
</li>
<li>
<label for="request">&nbsp;</label>
<button name="request" @click="removeRequestBodyParam(index)">Remove</button>
</li>
</ol>
<ul>
<li>
<label for="addrequest">Action</label>
<button name="addrequest" @click="addRequestBodyParam">Add</button>
</li>
</ul>
<ul>
<li>
<label for="request">Parameter List</label>
<textarea name="request" rows="1" readonly>{{rawRequestBody || '(add at least one parameter)'}}</textarea>
</li>
</ul>
</div>
</fieldset>
<fieldset class="authentication hidden">
<legend v-on:click="collapse">Authentication ↕</legend>
<div class="collapsible">
<ul>
<li>
<label for="auth">Authentication Type</label>
<select v-model="auth">
<option>None</option>
<option>Basic</option>
<option>Bearer Token</option>
</select>
</li>
</ul>
<ul v-if="auth === 'Basic'">
<li>
<label for="http_basic_user">User</label>
<input v-model="httpUser">
</li>
<li>
<label for="http_basic_passwd">Password</label>
<input v-model="httpPassword" type="password">
</li>
</ul>
<ul v-if="auth === 'Bearer Token'">
<li>
<label for="bearer_token">Token</label>
<input v-model="bearerToken">
</li>
</ul>
</div>
</fieldset>
<fieldset class="parameters hidden">
<legend v-on:click="collapse">Parameters ↕</legend>
<div class="collapsible">
<ol v-for="(param, index) in params">
<li>
<label :for="'param'+index">Key {{index + 1}}</label>
<input :name="'param'+index" v-model="param.key">
</li>
<li>
<label :for="'value'+index">Value {{index + 1}}</label>
<input :name="'value'+index" v-model="param.value">
</li>
<li>
<label for="param">&nbsp;</label>
<button name="param" @click="removeRequestParam(index)">Remove</button>
</li>
</ol>
<ul>
<li>
<label for="add">Action</label>
<button name="add" @click="addRequestParam">Add</button>
</li>
</ul>
<ul>
<li>
<label for="request">Parameter List</label>
<textarea name="request" rows="1" readonly>{{queryString || '(add at least one parameter)'}}</textarea>
</li>
</ul>
</div>
</fieldset>
<fieldset class="response" id="response" ref="response">
<legend v-on:click="collapse">Response ↕</legend>
<div class="collapsible">
<ul>
<li>
<label for="status">status</label>
<input name="status" type="text" readonly :value="response.status || '(waiting to send request)'">
</li>
</ul>
<ul v-for="(value, key) in response.headers">
<li>
<label for="value">{{key}}</label>
<input name="value" :value="value" readonly>
</li>
</ul>
<ul>
<li>
<label for="body">response</label>
<textarea name="body" rows="10" readonly>{{response.body || '(waiting to send request)'}}</textarea>
</li>
</ul>
</div>
</fieldset>
<fieldset class="history">
<legend v-on:click="collapse">History ↕</legend>
<div class="collapsible">
<ul>
<li>
<button v-bind:class="{ disabled: noHistoryToClear }" v-on:click="clearHistory">Clear History</button>
</li>
</ul>
<ul v-for="entry in history">
<li>
<label for="time">Time</label>
<input name="time" type="text" readonly :value="entry.time">
</li>
<li>
<label for="name">Method</label>
<input name="name" type="text" readonly :value="entry.method">
</li>
<li>
<label for="name">URL</label>
<input name="name" type="text" readonly :value="entry.url">
</li>
<li>
<label for="name">Path</label>
<input name="name" type="text" readonly :value="entry.path">
</li>
<li>
<label for="delete">&nbsp;</label>
<button name="delete" @click="deleteHistory(entry)">Delete</button>
</li>
<li>
<label for="use">&nbsp;</label>
<button name="use" @click="useHistory(entry)">Use</button>
</li>
</ul>
</div>
</fieldset>
<footer>
<a href="https://github.com/liyasthomas/postwoman" target="_blank"><img src="icons/github.svg" alt="" style="margin-right: 16px">GitHub</a>
<button id="installPWA" onclick="installPWA()">
Install PWA
</button>
</footer>
</main>
<script src="script.js"></script>
<script>
let pwaInstalled = localStorage.getItem('pwaInstalled') == 'yes'
if (window.matchMedia('(display-mode: standalone)').matches) {
localStorage.setItem('pwaInstalled', 'yes')
pwaInstalled = true
}
if (window.navigator.standalone === true) {
localStorage.setItem('pwaInstalled', 'yes')
pwaInstalled = true
}
if (pwaInstalled) {
document.getElementById('installPWA').style.display = 'none'
} else {
document.getElementById('installPWA').style.display = 'block'
}
let deferredPrompt = null
window.addEventListener('beforeinstallprompt', (e) => {
deferredPrompt = e
})
async function installPWA() {
if (deferredPrompt) {
deferredPrompt.prompt()
deferredPrompt.userChoice.then(({
outcome
}) => {
if (outcome === 'accepted') {
console.log('Your PWA has been installed')
} else {
console.log('User chose to not install your PWA')
}
deferredPrompt = null
})
}
}
window.addEventListener('appinstalled', (evt) => {
localStorage.setItem('pwaInstalled', 'yes')
pwaInstalled = true
document.getElementById('installPWA').style.display = 'none'
})
</script>
</body>
</html>

12
jsconfig.json Normal file
View File

@@ -0,0 +1,12 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"~/*": ["./*"],
"@/*": ["./*"],
"~~/*": ["./*"],
"@@/*": ["./*"]
}
},
"exclude": ["node_modules", ".nuxt", "dist"]
}

7
layouts/README.md Normal file
View File

@@ -0,0 +1,7 @@
# LAYOUTS
**This directory is not required, you can delete it if you don't want to use it.**
This directory contains your Application Layouts.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/views#layouts).

62
layouts/default.vue Normal file
View File

@@ -0,0 +1,62 @@
<template>
<div>
<header>
<div class="slide-in">
<nuxt-link to="/">
<h1 class="logo"><img src="~static/icons/logo.svg" alt="" style="height: 24px; margin-right: 16px">Postwoman</h1>
</nuxt-link>
<h3>Lightweight API request builder</h3>
</div>
</header>
<nuxt id="main" />
<footer>
<a href="https://github.com/liyasthomas/postwoman" target="_blank"><img src="~static/icons/github.svg" alt="" style="margin-right: 16px">GitHub</a>
<button id="installPWA" @click.prevent="showInstallPrompt()">
Install PWA
</button>
</footer>
</div>
</template>
<style lang="scss">
.slide-in {
position: relative;
animation: slideIn 0.4s forwards ease-in-out;
}
@keyframes slideIn {
0% {
opacity: 0;
left: -30px;
}
100% {
opacity: 1;
left: 0px;
}
}
header, #main, footer {
margin: 0 auto;
max-width: 1200px;
}
</style>
<script>
import intializePwa from '../assets/js/pwa';
export default {
data () {
return {
showInstallPrompt: null
}
},
mounted () {
(async () => {
this.showInstallPrompt = await intializePwa();
})();
}
}
</script>

35
layouts/error.vue Normal file
View File

@@ -0,0 +1,35 @@
<template>
<div class="page page-error">
<h1>{{ error.statusCode }}</h1>
<h2>{{ error.message }}</h2>
<br>
<p><nuxt-link to="/"><button>Go Home</button></nuxt-link></p>
<p><a href="/">Reload</a></p>
</div>
</template>
<style lang="scss">
// Center the error page in the viewport.
.page-error {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
text-align: center;
}
</style>
<script>
export default {
props: ['error'],
head () {
return {
bodyAttrs: {
class: 'sticky-footer'
}
}
}
}
</script>

View File

@@ -1,41 +0,0 @@
{
"name": "Postwoman",
"short_name": "Postwoman",
"description": "API request builder",
"icons": [
{
"src": "icons/icon-48x48.png",
"sizes": "48x48",
"type": "image/png"
},
{
"src": "icons/icon-72x72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "icons/icon-96x96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "icons/icon-144x144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"start_url": "./",
"display": "standalone",
"theme_color": "#121212",
"background_color": "#121212"
}

8
middleware/README.md Normal file
View File

@@ -0,0 +1,8 @@
# MIDDLEWARE
**This directory is not required, you can delete it if you don't want to use it.**
This directory contains your application middleware.
Middleware let you define custom functions that can be run before rendering either a page or a group of pages.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing#middleware).

138
nuxt.config.js Normal file
View File

@@ -0,0 +1,138 @@
// Some helpful application constants.
// TODO: Use these when rendering the pages (rather than just for head/meta tags...)
const meta = {
name: "Postwoman",
shortDescription: "Lightweight API request builder",
description: "The Postwoman API request builder helps you create your requests faster, saving you precious time on your development."
};
export default {
mode: 'spa',
/*
** Headers of the page
*/
head: {
title: `${meta.name} \u2022 ${meta.shortDescription}`,
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1, minimum-scale=1, shrink-to-fit=no, minimal-ui' },
{ hid: 'description', name: 'description', content: meta.description || '' },
{ name: 'X-UA-Compatible', content: "IE=edge, chrome=1" },
{ itemprop: "name", content: `${meta.name} \u2022 ${meta.shortDescription}` },
{ itemprop: "description", content: meta.description },
{ itemprop: "image", content: "/icons/icon-192x192.png" },
// Add to homescreen for Chrome on Android. Fallback for PWA (handled by nuxt)
{ name: 'application-name', content: meta.name },
// Add to homescreen for Safari on iOS
{ name: 'apple-mobile-web-app-capable', content: 'yes' },
{ name: 'apple-mobile-web-app-status-bar-style', content: 'black-translucent' },
{ name: 'apple-mobile-web-app-title', content: meta.name },
// Windows phone tile icon
{ name: 'msapplication-TileImage', content: 'icons/icon-144x144.png' },
{ name: 'msapplication-TileColor', content: '#121212' },
{ name: 'msapplication-tap-highlight', content: 'no' },
// OpenGraph
{ property: 'og:site_name', content: meta.name },
{ property: 'og:url', content: 'https://liyasthomas.github.io/postwoman' },
{ property: 'og:type', content: 'website' },
{ property: 'og:title', content: `${meta.name} \u2022 ${meta.shortDescription}` },
{ property: 'og:description', content: meta.description },
{ property: 'og:image', content: '/icons/icon-144x144.png' },
// Twitter
{ name: 'twitter:card', content: "summary" },
{ name: 'twitter:site', content: "@liyasthomas" },
{ name: 'twitter:creator', content: "@liyasthomas" },
{ name: 'twitter:url', content: "https://liyasthomas.github.io/postwoman" },
{ name: 'twitter:title', content: meta.name },
{ name: 'twitter:description', content: meta.shortDescription },
{ name: 'twitter:image', content: '/icons/icon-144x144.png' },
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
// Home-screen icons (iOS)
{ rel: 'apple-touch-icon', href: '/icons/icon-48x48.png' },
{ rel: 'apple-touch-icon', sizes: '72x72', href: '/icons/icon-72x72.png' },
{ rel: 'apple-touch-icon', sizes: '96x96', href: '/icons/icon-96x96.png' },
{ rel: 'apple-touch-icon', sizes: '144x144', href: '/icons/icon-144x144.png' },
{ rel: 'apple-touch-icon', sizes: '192x192', href: '/icons/icon-192x192.png' },
]
},
/*
** Customize the progress-bar color
*/
loading: { color: '#88FB4F' },
/*
** Global CSS
*/
css: [
'@/assets/css/fonts.scss',
'@/assets/css/styles.scss'
],
/*
** Plugins to load before mounting the App
*/
plugins: [
],
/*
** Nuxt.js dev-modules
*/
buildModules: [
],
/*
** Nuxt.js modules
*/
modules: [
// See https://goo.gl/OOhYW5
['@nuxtjs/pwa', {
manifest: {
name: meta.name,
short_name: meta.name,
description: meta.shortDescription,
display: "standalone",
theme_color: "#121212",
background_color: "#121212",
icons: ((sizes) => {
let icons = [];
for(let size of sizes){
icons.push({
"src": `/icons/icon-${size}x${size}.png`,
"type": "image/png",
"sizes": `${size}x${size}`
});
}
return icons;
})([48, 72, 96, 144, 192, 512])
}
}]
],
/*
** Build configuration
*/
build: {
/*
** You can extend webpack config here
*/
extend (config, ctx) {
}
},
/*
** Generate configuration
*/
generate: {
fallback: true
}
}

11139
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +1,21 @@
{ {
"name": "Postwoman", "name": "postwoman",
"repository": { "version": "1.0.0",
"type": "git", "description": "Lightweight API request builder by Liyas Thomas",
"url": "https://github.com/liyasthomas/postwoman.git" "author": "liyasthomas",
}, "private": true,
"description": "API request builder", "scripts": {
"author": "liyasthomas", "dev": "nuxt",
"version": "0.1.0", "build": "nuxt build",
"devDependencies": { "start": "nuxt start",
"http-server": "^0.11.1", "generate": "nuxt generate"
"jshint": "^2.10.2" },
}, "dependencies": {
"scripts": { "nuxt": "^2.0.0",
"start": "http-server -c-1", "@nuxtjs/pwa": "^3.0.0-0"
"test": "jshint travis.js" },
} "devDependencies": {
"node-sass": "^4.12.0",
"sass-loader": "^7.3.1"
}
} }

6
pages/README.md Normal file
View File

@@ -0,0 +1,6 @@
# PAGES
This directory contains your Application Views and Routes.
The framework reads all the `*.vue` files inside this directory and creates the router of your application.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing).

380
pages/index.vue Normal file
View File

@@ -0,0 +1,380 @@
<template>
<div class="page">
<fieldset class="request" ref="request">
<legend v-on:click="collapse">Request </legend>
<div class="collapsible">
<ul>
<li>
<label for="method">Method</label>
<select v-model="method">
<option>GET</option>
<option>POST</option>
<option>PUT</option>
<option>DELETE</option>
<option>OPTIONS</option>
</select>
</li>
<li>
<label for="url">URL</label>
<input type="url" v-bind:class="{ error: urlNotValid }" v-model="url" v-on:keyup.enter="sendRequest">
</li>
<li>
<label for="path">Path</label>
<input v-model="path" v-on:keyup.enter="sendRequest">
</li>
<li>
<label for="action">&nbsp;</label>
<button v-bind:class="{ disabled: urlNotValid }" name="action" @click="sendRequest">Send</button>
</li>
</ul>
</div>
</fieldset>
<fieldset class="reqbody" v-if="method === 'POST' || method === 'PUT'">
<legend v-on:click="collapse">Request Body </legend>
<div class="collapsible">
<ul>
<li>
<label>Content Type</label>
<select v-model="contentType">
<option>application/json</option>
<option>www-form/urlencoded</option>
</select>
</li>
</ul>
<ol v-for="(param, index) in bodyParams">
<li>
<label :for="'bparam'+index">Key {{index + 1}}</label>
<input :name="'bparam'+index" v-model="param.key">
</li>
<li>
<label :for="'bvalue'+index">Value {{index + 1}}</label>
<input :name="'bvalue'+index" v-model="param.value">
</li>
<li>
<label for="request">&nbsp;</label>
<button name="request" @click="removeRequestBodyParam(index)">Remove</button>
</li>
</ol>
<ul>
<li>
<label for="addrequest">Action</label>
<button name="addrequest" @click="addRequestBodyParam">Add</button>
</li>
</ul>
<ul>
<li>
<label for="request">Parameter List</label>
<textarea name="request" rows="1" readonly>{{rawRequestBody || '(add at least one parameter)'}}</textarea>
</li>
</ul>
</div>
</fieldset>
<fieldset class="authentication hidden">
<legend v-on:click="collapse">Authentication </legend>
<div class="collapsible">
<ul>
<li>
<label for="auth">Authentication Type</label>
<select v-model="auth">
<option>None</option>
<option>Basic</option>
<option>Bearer Token</option>
</select>
</li>
</ul>
<ul v-if="auth === 'Basic'">
<li>
<label for="http_basic_user">User</label>
<input v-model="httpUser">
</li>
<li>
<label for="http_basic_passwd">Password</label>
<input v-model="httpPassword" type="password">
</li>
</ul>
<ul v-if="auth === 'Bearer Token'">
<li>
<label for="bearer_token">Token</label>
<input v-model="bearerToken">
</li>
</ul>
</div>
</fieldset>
<fieldset class="parameters hidden">
<legend v-on:click="collapse">Parameters </legend>
<div class="collapsible">
<ol v-for="(param, index) in params">
<li>
<label :for="'param'+index">Key {{index + 1}}</label>
<input :name="'param'+index" v-model="param.key">
</li>
<li>
<label :for="'value'+index">Value {{index + 1}}</label>
<input :name="'value'+index" v-model="param.value">
</li>
<li>
<label for="param">&nbsp;</label>
<button name="param" @click="removeRequestParam(index)">Remove</button>
</li>
</ol>
<ul>
<li>
<label for="add">Action</label>
<button name="add" @click="addRequestParam">Add</button>
</li>
</ul>
<ul>
<li>
<label for="request">Parameter List</label>
<textarea name="request" rows="1" readonly>{{queryString || '(add at least one parameter)'}}</textarea>
</li>
</ul>
</div>
</fieldset>
<fieldset class="response" id="response" ref="response">
<legend v-on:click="collapse">Response </legend>
<div class="collapsible">
<ul>
<li>
<label for="status">status</label>
<input name="status" type="text" readonly :value="response.status || '(waiting to send request)'">
</li>
</ul>
<ul v-for="(value, key) in response.headers">
<li>
<label for="value">{{key}}</label>
<input name="value" :value="value" readonly>
</li>
</ul>
<ul>
<li>
<label for="body">response</label>
<textarea name="body" rows="10" readonly>{{response.body || '(waiting to send request)'}}</textarea>
</li>
</ul>
</div>
</fieldset>
<fieldset class="history">
<legend v-on:click="collapse">History </legend>
<div class="collapsible">
<ul>
<li>
<button v-bind:class="{ disabled: noHistoryToClear }" v-on:click="clearHistory">Clear History</button>
</li>
</ul>
<ul v-for="entry in history">
<li>
<label for="time">Time</label>
<input name="time" type="text" readonly :value="entry.time">
</li>
<li>
<label for="name">Method</label>
<input name="name" type="text" readonly :value="entry.method">
</li>
<li>
<label for="name">URL</label>
<input name="name" type="text" readonly :value="entry.url">
</li>
<li>
<label for="name">Path</label>
<input name="name" type="text" readonly :value="entry.path">
</li>
<li>
<label for="delete">&nbsp;</label>
<button name="delete" @click="deleteHistory(entry)">Delete</button>
</li>
<li>
<label for="use">&nbsp;</label>
<button name="use" @click="useHistory(entry)">Use</button>
</li>
</ul>
</div>
</fieldset>
</div>
</template>
<script>
const parseHeaders = xhr => {
const headers = xhr.getAllResponseHeaders().trim().split(/[\r\n]+/);
const headerMap = {};
headers.forEach(line => {
const parts = line.split(': ');
const header = parts.shift().toLowerCase();
const value = parts.join(': ');
headerMap[header] = value
});
return headerMap
};
export default {
data () {
return {
method: 'GET',
url: 'https://reqres.in',
auth: 'None',
path: '/api/users',
httpUser: '',
httpPassword: '',
bearerToken: '',
params: [],
bodyParams: [],
contentType: 'application/json',
response: {
status: '',
headers: '',
body: ''
},
history: window.localStorage.getItem('history') ? JSON.parse(window.localStorage.getItem('history')) : []
}
},
computed: {
noHistoryToClear() {
return this.history.length === 0;
},
urlNotValid() {
const pattern = new RegExp('^(https?:\\/\\/)?' +
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' +
'((\\d{1,3}\\.){3}\\d{1,3}))' +
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' +
'(\\?[;&a-z\\d%_.~+=-]*)?' +
'(\\#[-a-z\\d_]*)?$', 'i')
return !pattern.test(this.url)
},
rawRequestBody() {
const {
bodyParams
} = this
if (this.contentType === 'application/json') {
try {
const obj = JSON.parse(`{${bodyParams.filter(({ key }) => !!key).map(({ key, value }) => `
"${key}": "${value}"
`).join()}}`)
return JSON.stringify(obj)
} catch (ex) {
return 'invalid'
}
} else {
return bodyParams
.filter(({
key
}) => !!key)
.map(({
key,
value
}) => `${key}=${encodeURIComponent(value)}`).join('&')
}
},
queryString() {
const result = this.params
.filter(({
key
}) => !!key)
.map(({
key,
value
}) => `${key}=${encodeURIComponent(value)}`).join('&')
return result == '' ? '' : `?${result}`
}
},
methods: {
deleteHistory(entry) {
this.history.splice(this.history.indexOf(entry), 1)
window.localStorage.setItem('history', JSON.stringify(this.history))
},
clearHistory() {
this.history = []
window.localStorage.setItem('history', JSON.stringify(this.history))
},
useHistory({
method,
url,
path
}) {
this.method = method
this.url = url
this.path = path
this.$refs.request.scrollIntoView({
behavior: 'smooth'
})
},
collapse({
target
}) {
const el = target.parentNode.className
document.getElementsByClassName(el)[0].classList.toggle('hidden')
},
sendRequest() {
if (this.urlNotValid) {
alert('Please check the formatting of the URL')
return
}
const n = new Date().toLocaleTimeString()
this.history = [{
time: n,
method: this.method,
url: this.url,
path: this.path
}, ...this.history]
window.localStorage.setItem('history', JSON.stringify(this.history))
if (this.$refs.response.classList.contains('hidden')) {
this.$refs.response.classList.toggle('hidden')
}
this.$refs.response.scrollIntoView({
behavior: 'smooth'
})
this.response.status = 'Fetching...'
this.response.body = 'Loading...'
const xhr = new XMLHttpRequest()
const user = this.auth === 'Basic' ? this.httpUser : null
const pswd = this.auth === 'Basic' ? this.httpPassword : null
xhr.open(this.method, this.url + this.path + this.queryString, true, user, pswd)
if (this.auth === 'Bearer Token') {
xhr.setRequestHeader('Authorization', 'Bearer ' + this.bearerToken);
}
if (this.method === 'POST' || this.method === 'PUT') {
const requestBody = this.rawRequestBody
xhr.setRequestHeader('Content-Length', requestBody.length)
xhr.setRequestHeader('Content-Type', `${this.contentType}; charset=utf-8`)
xhr.send(requestBody)
} else {
xhr.send()
}
xhr.onload = e => {
this.response.status = xhr.status
const headers = this.response.headers = parseHeaders(xhr)
if ((headers['content-type'] || '').startsWith('application/json')) {
this.response.body = JSON.stringify(JSON.parse(xhr.responseText), null, 2)
} else {
this.response.body = xhr.responseText
}
}
xhr.onerror = e => {
this.response.status = xhr.status
this.response.body = xhr.statusText
}
},
addRequestParam() {
this.params.push({
key: '',
value: ''
})
return false
},
removeRequestParam(index) {
this.params.splice(index, 1)
},
addRequestBodyParam() {
this.bodyParams.push({
key: '',
value: ''
})
return false
},
removeRequestBodyParam(index) {
this.bodyParams.splice(index, 1)
}
}
}
</script>

7
plugins/README.md Normal file
View File

@@ -0,0 +1,7 @@
# PLUGINS
**This directory is not required, you can delete it if you don't want to use it.**
This directory contains Javascript plugins that you want to run before mounting the root Vue.js application.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/plugins).

179
script.js
View File

@@ -1,179 +0,0 @@
const parseHeaders = xhr => {
const headers = xhr.getAllResponseHeaders().trim().split(/[\r\n]+/)
const headerMap = {}
headers.forEach(line => {
const parts = line.split(': ')
const header = parts.shift().toLowerCase()
const value = parts.join(': ')
headerMap[header] = value
})
return headerMap
}
const app = new Vue({
el: '#app',
data: {
method: 'GET',
url: 'https://reqres.in',
auth: 'None',
path: '/api/users',
httpUser: '',
httpPassword: '',
bearerToken: '',
params: [],
bodyParams: [],
contentType: 'application/json',
response: {
status: '',
headers: '',
body: ''
},
history: window.localStorage.getItem('history') ? JSON.parse(window.localStorage.getItem('history')) : []
},
computed: {
noHistoryToClear() {
return this.history.length === 0;
},
urlNotValid() {
const pattern = new RegExp('^(https?:\\/\\/)?' +
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' +
'((\\d{1,3}\\.){3}\\d{1,3}))' +
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' +
'(\\?[;&a-z\\d%_.~+=-]*)?' +
'(\\#[-a-z\\d_]*)?$', 'i')
return !pattern.test(this.url)
},
rawRequestBody() {
const {
bodyParams
} = this
if (this.contentType === 'application/json') {
try {
const obj = JSON.parse(`{${bodyParams.filter(({ key }) => !!key).map(({ key, value }) => `
"${key}": "${value}"
`).join()}}`)
return JSON.stringify(obj)
} catch (ex) {
return 'invalid'
}
} else {
return bodyParams
.filter(({
key
}) => !!key)
.map(({
key,
value
}) => `${key}=${encodeURIComponent(value)}`).join('&')
}
},
queryString() {
const result = this.params
.filter(({
key
}) => !!key)
.map(({
key,
value
}) => `${key}=${encodeURIComponent(value)}`).join('&')
return result == '' ? '' : `?${result}`
}
},
methods: {
deleteHistory(entry) {
this.history.splice(this.history.indexOf(entry), 1)
window.localStorage.setItem('history', JSON.stringify(this.history))
},
clearHistory() {
this.history = []
window.localStorage.setItem('history', JSON.stringify(this.history))
},
useHistory({
method,
url,
path
}) {
this.method = method
this.url = url
this.path = path
this.$refs.request.scrollIntoView({
behavior: 'smooth'
})
},
collapse({
target
}) {
const el = target.parentNode.className
document.getElementsByClassName(el)[0].classList.toggle('hidden')
},
sendRequest() {
if (this.urlNotValid) {
alert('Please check the formatting of the URL')
return
}
const n = new Date().toLocaleTimeString()
this.history = [{
time: n,
method: this.method,
url: this.url,
path: this.path
}, ...this.history]
window.localStorage.setItem('history', JSON.stringify(this.history))
if (this.$refs.response.classList.contains('hidden')) {
this.$refs.response.classList.toggle('hidden')
}
this.$refs.response.scrollIntoView({
behavior: 'smooth'
})
this.response.status = 'Fetching...'
this.response.body = 'Loading...'
const xhr = new XMLHttpRequest()
const user = this.auth === 'Basic' ? this.httpUser : null
const pswd = this.auth === 'Basic' ? this.httpPassword : null
xhr.open(this.method, this.url + this.path + this.queryString, true, user, pswd)
if (this.auth === 'Bearer Token') {
xhr.setRequestHeader('Authorization', 'Bearer ' + this.bearerToken);
}
if (this.method === 'POST' || this.method === 'PUT') {
const requestBody = this.rawRequestBody
xhr.setRequestHeader('Content-Length', requestBody.length)
xhr.setRequestHeader('Content-Type', `${this.contentType}; charset=utf-8`)
xhr.send(requestBody)
} else {
xhr.send()
}
xhr.onload = e => {
this.response.status = xhr.status
const headers = this.response.headers = parseHeaders(xhr)
if ((headers['content-type'] || '').startsWith('application/json')) {
this.response.body = JSON.stringify(JSON.parse(xhr.responseText), null, 2)
} else {
this.response.body = xhr.responseText
}
}
xhr.onerror = e => {
this.response.status = xhr.status
this.response.body = xhr.statusText
}
},
addRequestParam() {
this.params.push({
key: '',
value: ''
})
return false
},
removeRequestParam(index) {
this.params.splice(index, 1)
},
addRequestBodyParam() {
this.bodyParams.push({
key: '',
value: ''
})
return false
},
removeRequestBodyParam(index) {
this.bodyParams.splice(index, 1)
}
}
})

11
static/README.md Normal file
View File

@@ -0,0 +1,11 @@
# STATIC
**This directory is not required, you can delete it if you don't want to use it.**
This directory contains your static files.
Each file inside this directory is mapped to `/`.
Thus you'd want to delete this README.md before deploying to production.
Example: `/static/robots.txt` is mapped as `/robots.txt`.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#static).

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

View File

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

10
store/README.md Normal file
View File

@@ -0,0 +1,10 @@
# STORE
**This directory is not required, you can delete it if you don't want to use it.**
This directory contains your Vuex Store files.
Vuex Store option is implemented in the Nuxt.js framework.
Creating a file in this directory automatically activates the option in the framework.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/vuex-store).

148
sw.js
View File

@@ -1,148 +0,0 @@
importScripts('https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js');
if (workbox) {
console.log(`Yay! Workbox is loaded 🎉`);
} else {
console.log(`Boo! Workbox didn't load 😬`);
}
workbox.routing.registerRoute(
new RegExp('.*\.js'),
new workbox.strategies.NetworkFirst()
);
workbox.routing.registerRoute(
// Cache CSS files.
/\.css$/,
// Use cache but update in the background.
new workbox.strategies.StaleWhileRevalidate({
// Use a custom cache name.
cacheName: 'css-cache',
})
);
workbox.routing.registerRoute(
// Cache image files.
/\.(?:png|jpg|jpeg|svg|gif)$/,
// Use the cache if it's available.
new workbox.strategies.CacheFirst({
// Use a custom cache name.
cacheName: 'image-cache',
plugins: [
new workbox.expiration.Plugin({
// Cache only 20 images.
maxEntries: 20,
// Cache for a maximum of a week.
maxAgeSeconds: 7 * 24 * 60 * 60,
})
],
})
);
workbox.precaching.precacheAndRoute([
'/postwoman/style.css',
'/postwoman/script.js',
{
url: '/postwoman/index.html',
revision: '383676'
},
]);
var CACHE_VERSION = 1;
var CURRENT_CACHES = {
prefetch: 'prefetch-cache-v' + CACHE_VERSION
};
self.addEventListener('install', function (event) {
var now = Date.now();
var urlsToPrefetch = [
'/postwoman/index.html',
];
// All of these logging statements should be visible via the "Inspect" interface
// for the relevant SW accessed via chrome://serviceworker-internals
console.log('Handling install event. Resources to prefetch:', urlsToPrefetch);
event.waitUntil(
caches.open(CURRENT_CACHES.prefetch).then(function (cache) {
var cachePromises = urlsToPrefetch.map(function (urlToPrefetch) {
// This constructs a new URL object using the service worker's script location as the base
// for relative URLs.
var url = new URL(urlToPrefetch, location.href);
// Append a cache-bust=TIMESTAMP URL parameter to each URL's query string.
// This is particularly important when precaching resources that are later used in the
// fetch handler as responses directly, without consulting the network (i.e. cache-first).
// If we were to get back a response from the HTTP browser cache for this precaching request
// then that stale response would be used indefinitely, or at least until the next time
// the service worker script changes triggering the install flow.
url.search += (url.search ? '&' : '?') + 'cache-bust=' + now;
// It's very important to use {mode: 'no-cors'} if there is any chance that
// the resources being fetched are served off of a server that doesn't support
// CORS (http://en.wikipedia.org/wiki/Cross-origin_resource_sharing).
// In this example, www.chromium.org doesn't support CORS, and the fetch()
// would fail if the default mode of 'cors' was used for the fetch() request.
// The drawback of hardcoding {mode: 'no-cors'} is that the response from all
// cross-origin hosts will always be opaque
// (https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#cross-origin-resources)
// and it is not possible to determine whether an opaque response represents a success or failure
// (https://github.com/whatwg/fetch/issues/14).
var request = new Request(url, {
mode: 'no-cors'
});
return fetch(request).then(function (response) {
if (response.status >= 400) {
throw new Error('request for ' + urlToPrefetch +
' failed with status ' + response.statusText);
}
// Use the original URL without the cache-busting parameter as the key for cache.put().
return cache.put(urlToPrefetch, response);
}).catch(function (error) {
console.error('Not caching ' + urlToPrefetch + ' due to ' + error);
});
});
return Promise.all(cachePromises).then(function () {
console.log('Pre-fetching complete.');
});
}).catch(function (error) {
console.error('Pre-fetching failed:', error);
})
);
});
self.addEventListener('activate', function (event) {
// Delete all caches that aren't named in CURRENT_CACHES.
// While there is only one cache in this example, the same logic will handle the case where
// there are multiple versioned caches.
var expectedCacheNames = Object.keys(CURRENT_CACHES).map(function (key) {
return CURRENT_CACHES[key];
});
event.waitUntil(
caches.keys().then(function (cacheNames) {
return Promise.all(
cacheNames.map(function (cacheName) {
if (expectedCacheNames.indexOf(cacheName) === -1) {
// If this cache name isn't present in the array of "expected" cache names, then delete it.
console.log('Deleting out of date cache:', cacheName);
return caches.delete(cacheName);
}
})
);
})
);
});
self.addEventListener('fetch', function (event) {
console.log('Handling fetch event for', event.request.url);
event.respondWith(
// caches.match() will look for a cache entry in all of the caches available to the service worker.
// It's an alternative to first opening a specific named cache and then matching on that.
caches.match(event.request).then(function (response) {
if (response) {
console.log('Found response in cache:', response);
return response;
}
console.log('No response found in cache. About to fetch from network...');
// event.request will always have the proper mode set ('cors, 'no-cors', etc.) so we don't
// have to hardcode 'no-cors' like we do when fetch()ing in the install handler.
return fetch(event.request).then(function (response) {
console.log('Response from network is:', response);
return response;
}).catch(function (error) {
// This catch() will handle exceptions thrown from the fetch() operation.
// Note that a HTTP error response (e.g. 404) will NOT trigger an exception.
// It will return a normal response object that has the appropriate error code set.
console.error('Fetching failed:', error);
throw error;
});
})
);
});