├── .gitignore ├── .npmignore ├── .vscode └── launch.json ├── README.md ├── category-aliases-db.json ├── controllers ├── db-routes.js └── json-routes.js ├── dist ├── 3rdpartylicenses.txt ├── assets │ └── sakura-dark.css ├── favicon.ico ├── index.html ├── main.js ├── main.js.map ├── polyfills.js ├── polyfills.js.map ├── runtime.js ├── runtime.js.map ├── styles.js ├── styles.js.map ├── vendor.js └── vendor.js.map ├── index.js ├── package-lock.json ├── package.json ├── readme-images ├── snippets-export.png ├── snippets-intro.png ├── snippets-outro.png ├── snippets-part-1.gif ├── snippets-part-2.gif ├── snippets-part-3.gif ├── snippets-results.png └── snippets-snippet.png ├── routes.js ├── snippets.code-workspace └── snippets ├── .editorconfig ├── .gitignore ├── README.md ├── angular.json ├── e2e ├── app.e2e-spec.ts ├── app.po.ts └── tsconfig.e2e.json ├── karma.conf.js ├── package-lock.json ├── package.json ├── protractor.conf.js ├── src ├── app │ ├── add-snippet │ │ ├── add-snippet.component.css │ │ ├── add-snippet.component.html │ │ ├── add-snippet.component.spec.ts │ │ └── add-snippet.component.ts │ ├── app.component.css │ ├── app.component.html │ ├── app.component.spec.ts │ ├── app.component.ts │ ├── app.module.ts │ ├── build-cover-letter │ │ ├── build-cover-letter.component.css │ │ ├── build-cover-letter.component.html │ │ ├── build-cover-letter.component.spec.ts │ │ └── build-cover-letter.component.ts │ ├── category-aliases-db │ │ ├── category-aliases-db.component.css │ │ ├── category-aliases-db.component.html │ │ ├── category-aliases-db.component.spec.ts │ │ └── category-aliases-db.component.ts │ ├── cover-letter │ │ ├── cover-letter.component.css │ │ ├── cover-letter.component.html │ │ ├── cover-letter.component.spec.ts │ │ └── cover-letter.component.ts │ ├── database │ │ ├── database.component.css │ │ ├── database.component.html │ │ ├── database.component.spec.ts │ │ └── database.component.ts │ ├── export │ │ ├── export.component.css │ │ ├── export.component.html │ │ ├── export.component.spec.ts │ │ └── export.component.ts │ ├── has-keywords.pipe.spec.ts │ ├── has-keywords.pipe.ts │ ├── job-description │ │ ├── job-description.component.css │ │ ├── job-description.component.html │ │ ├── job-description.component.spec.ts │ │ └── job-description.component.ts │ ├── nav │ │ ├── nav.component.css │ │ ├── nav.component.html │ │ ├── nav.component.spec.ts │ │ └── nav.component.ts │ ├── results │ │ ├── results.component.css │ │ ├── results.component.html │ │ ├── results.component.spec.ts │ │ └── results.component.ts │ ├── services │ │ ├── cover-letter.service.spec.ts │ │ ├── cover-letter.service.ts │ │ ├── database.service.db.spec.ts │ │ ├── database.service.json.spec.ts │ │ ├── database.service.ts │ │ ├── databaseCategoryAliases.service.ts │ │ ├── parse-description.service.spec.ts │ │ ├── parse-description.service.ts │ │ ├── status-message.service.spec.ts │ │ └── status-message.service.ts │ └── status-message │ │ ├── status-message.component.css │ │ ├── status-message.component.html │ │ ├── status-message.component.spec.ts │ │ └── status-message.component.ts ├── assets │ ├── .gitkeep │ └── sakura-dark.css ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── favicon.ico ├── index.html ├── main.ts ├── polyfills.ts ├── styles.css ├── test-helpers.js ├── test.ts ├── tsconfig.app.json ├── tsconfig.spec.json └── typings.d.ts ├── tsconfig.json └── tslint.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | 63 | # vscode workspace 64 | *.code-workspace 65 | 66 | *snippets-db.json -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Ignore the Angular Development App 2 | /snippets/ 3 | 4 | # Ignore Created DB. 5 | ./snippets-db.json 6 | 7 | # vscode workspace 8 | *.code-workspace -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Unit tests", 9 | "type": "chrome", 10 | "request": "attach", 11 | "address": "localhost", 12 | "port": 9333, 13 | "webRoot": "${workspaceFolder}/snippets", 14 | // "outFiles": [ 15 | // "${workspaceFolder}/../dist/*.js" 16 | // ] 17 | }, 18 | { 19 | "name": "ng test", 20 | "type": "chrome", 21 | "request": "launch", 22 | "url": "http://localhost:9876/debug.html", 23 | "webRoot": "${workspaceFolder}" 24 | } 25 | ] 26 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cover Letter Snippets 2 | Cover Letter Snippets is an Angular/MongoDB/Node.js Express application that helps you figure out the keywords on a job listing and then compose a cover letter customized for the job by reusing the relevant content from your previous cover letters. 3 | 4 | Snippets 6 | 7 | ## Installing and Running Cover Letter Snippets 8 | 9 | Note: The following instructions have been tested for MacOS only. 10 | 11 | To install and run Cover Letter Snippets: 12 | 1. Run `npm i cover-letter-snippets` 13 | 14 | Note: In some cases, you might have to install the package globally: `npm i -g cover-letter-snippets` 15 | 16 | 2. Run `snippets` 17 | 18 | The application opens on the browser at `localhost:3141`. 19 | 20 | ## Configuring Cover Letter Snippets 21 | 22 | The easiest and recommended way to configure the application is to save the cover letter snippets as a JSON file on your local machine. To do so, click **Connect to JSON file** on the Database page. 23 | 24 | However, if you want to use the application across computers, you can store the cover letter snippets in a MongoDB database on MLab.com. This is an advanced use-case. For instructions to save the snippets in a MongoDB database, see [Save snippets in a MongoDB database](https://github.com/mattcheah/cover-letter-snippets#save-the-snippets-in-a-mongodb-database-optional). 25 | 26 | ## Using Cover Letter Snippets 27 | 28 | ![Connect to Database Gif](/readme-images/snippets-part-1.gif) 29 | 30 | ### Adding snippets 31 | 32 | Note: To add a snippet to the database, you need to have your existing cover letter(s) handy. 33 | 34 | 1. Navigate to the **Add Snippet** page. 35 | 2. From your existing cover letter, copy and paste a snippet related to one or more skills or technology. For example, add one snippet for a paragraph that describes your experience with Python. Add another snippet describing a side-project involving Go. 36 | 3. For each snippet, add the relevant keywords (comma separated, no spaces) in the **Categories** field. 37 | 38 | Important: The category names are case-sensitive. 39 | 40 | 4. Click **Submit Snippet**. 41 | 5. Add `intro` snippet and add the keyword `intro` to its **Categories** field. Click **Submit Snippet**. 42 | 6. Add an `outro` snippet and add the keyword `outro` in its **Categories** field. Click **Submit Snippet**. 43 | 44 | ### Editing snippets and categories 45 | 46 | To edit the snippets and their categories: 47 | 48 | 1. Navigate to the **Database** page. A table displaying the cover letter snippets is displayed. 49 | 2. Click on the snippet you want to edit and make the desired changes. 50 | 3. Click on the category you want to edit and make the desired changes. 51 | 4. Click off the table to save the changes. 52 | 53 | ### Building the cover letter 54 | 55 | To build the cover letter: 56 | 57 | 1. Navigate to the **Build Cover Letter** page. 58 | 2. Copy the job description for the job you want to apply to. Paste the job description in the text box. 59 | 3. Click **Parse Job Description**. A table containing a list of keywords, their frequency in the job description, and the relevant snippets appears. 60 | ![View Parsed Job Description and Category Matches](/readme-images/snippets-results.png) 61 | 4. Click **Show More**. 62 | 5. For the relevant snippet, click **Show Snippet**. 63 | 6. If you decide to include the snippet in the cover letter, click **Add** in the **Add to Letter** column. 64 | 7. Repeat step 6 for all relevant snippets. 65 | 8. Repeat steps 4-6 to add intro and outro snippets. 66 | ![Add snippets to your cover letter.](/readme-images/snippets-outro.png) 67 | 9. Reorder the snippets by clicking **Move Up** and **Move Down** as required. 68 | 10. Once you are done making all changes, click **Export and Tweak Cover Letter**. The Exported Cover Letter appears on the **Export Cover Letter** page. 69 | 11. Copy and paste the contents of the cover letter into a Word doc or Google doc. 70 | 71 | ![Connect to Database Gif](/readme-images/snippets-part-3.gif) 72 | 73 | ### Saving the snippets in a MongoDB database (optional) 74 | 75 | Note: This is an advanced use-case. 76 | 77 | If you plan to use the application across computers, you can store the cover letter snippets in the preconfigured MongoDB database or your own MongoDB database on MLab.com. 78 | 79 | If you want to play around with the app, there is a preconfigured database URI string in the form field. Please be a good person or I will have to take it out. Also, after you are done trying out the app, delete your entries from the database to ensure that other users don't see your entries. 80 | 81 | Alternatively, to store the snippets in your MongoDB database: 82 | 1. Go to mlab.com and sign up or log in. 83 | 2. Click **Create New** under Deployments. 84 | 3. Choose **AWS** and the **Free Sandbox** plan. 85 | 4. Pick a region and name your database. 86 | 5. Follow the prompts to submit and create your database. 87 | 6. Click on your new database. 88 | 7. Navigate to the **Users** tab and create a new user. 89 | 8. Fill out the username and password. 90 | 9. Copy the MongoDB URI for your database. 91 | 10. Navigate to the Cover Letter Snippets application. On the **Database** page, paste the MongoDB URI for your database. Replace the username/password with your credentials in the URI. 92 | 11. Click **Connect to Database**. 93 | 94 | # Contributing 95 | 96 | If you'd like to help, there's a ton of work that can be done to improve the product. Clone the repo and make a pull request! Off the top of my head, here are some things that can be done: 97 | 98 | - [Show Intro Snippets automatically after parsing job description](https://github.com/mattcheah/cover-letter-snippets/issues/1) 99 | - [Add button to show more snippets even if they haven't been mentioned in job desc.](https://github.com/mattcheah/cover-letter-snippets/issues/2) 100 | - [Create a fixed div as a sidebar that shows the parsed job description when you're adding snippets.](https://github.com/mattcheah/cover-letter-snippets/issues/4) 101 | - [Create an array of aliases for category names](https://github.com/mattcheah/cover-letter-snippets/issues/5) (ie. a job description listing 'RoR' or 'Ruby/Rails' would match your category of 'rails'. Each category and aliases would have to be set up by the user individually.) 102 | - [Sort addable snippets by which ones have the most relevant categories in the job description.](https://github.com/mattcheah/cover-letter-snippets/issues/6) 103 | 104 | # Other 105 | 106 | If you're looking to build a quick and easy resume, check out [Best Resume Ever](https://github.com/salomonelli/best-resume-ever) - I created the purple theme, which was based on how I styled my own resume. Check it out! 107 | -------------------------------------------------------------------------------- /category-aliases-db.json: -------------------------------------------------------------------------------- 1 | [{"_id":322143,"category":"cat10\n","aliases":["a1","a2"]},{"_id":247812,"category":"php\n\n","aliases":["php11"]}] -------------------------------------------------------------------------------- /controllers/db-routes.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | // CRUD routes for Mongoose db snippets entries. 4 | module.exports = { 5 | connectToDatabase: (req, res) => { 6 | 7 | const dburl = req.body.databaseUrl; 8 | 9 | if (dburl == "") { 10 | res.status(400).send("Please enter the URI of a mlab mongodb database!"); 11 | return; 12 | } 13 | 14 | let connection = mongoose.connect(dburl); 15 | mongoose.connection.on('error', function (err) { 16 | console.log("Error! " + err); 17 | res.status(400).json({ error: "Sorry, mongoose could not connect to the database! Make sure your URI is correct!" }); 18 | return; 19 | }); 20 | mongoose.connection.on('connected', function () { 21 | console.log("Successfully Connected!"); 22 | }); 23 | 24 | 25 | let Snippet = module.exports.setUpSchema(); 26 | module.exports.getAllSnippets(Snippet, "Successfully Connected to the Database and retrieved records!").then(data => { 27 | res.json(data); 28 | }); 29 | }, 30 | addSnippet: (req, res) => { 31 | const snippet = req.body.snippet; 32 | const categories = req.body.categories; 33 | let Snippet = module.exports.setUpSchema(); 34 | new Snippet({ 35 | snippet: snippet, 36 | categories: categories 37 | }).save(function (err) { 38 | if (err) { 39 | console.log("Error saving new snippet: " + err); 40 | res.error("Error adding snippet: " + err); 41 | } else { 42 | console.log("New Snippet Saved!"); 43 | module.exports.getAllSnippets(Snippet, "New Snippet Saved!").then(data => { 44 | res.json(data); 45 | }); 46 | } 47 | }); 48 | }, 49 | editSnippet: (req, res) => { 50 | let Snippet = module.exports.setUpSchema(); 51 | 52 | const id = req.body.id; 53 | const snippet = req.body.snippet; 54 | const categories = req.body.categories; 55 | 56 | Snippet.findById(id, function (err, response) { 57 | if(err) { 58 | res.status(400).json({ 59 | error: true, 60 | connected: true, 61 | data: [], 62 | responseMessage: err 63 | }); 64 | } 65 | response.snippet = snippet; 66 | response.categories = categories; 67 | response.save((err) => { 68 | if (err) { 69 | res.status(500).json({ 70 | error: true, 71 | connected: true, 72 | data: [], 73 | responseMessage: err 74 | }); 75 | } 76 | module.exports.getAllSnippets(Snippet, "Edited Snippet: " + snippet.substring(0, 30) + "...").then(data => { 77 | res.json(data); 78 | }); 79 | }); 80 | }); 81 | 82 | }, 83 | deleteSnippet: (req, res) => { 84 | const Snippet = module.exports.setUpSchema(); 85 | const id = req.body.id; 86 | let snippet; 87 | Snippet.findById(id, function (err, response) { 88 | let snippet = response; 89 | Snippet.findByIdAndRemove(id, function (err) { 90 | if (err) res.error("Error deleting snippet: " + err); 91 | module.exports.getAllSnippets(Snippet, "Removed Snippet: " + snippet.snippet.substring(0, 30) + "...").then(data => { 92 | res.json(data); 93 | }); 94 | }); 95 | }); 96 | }, 97 | getAllSnippets: (Snippet, successMessage) => { 98 | // Get all the snippets in the database; 99 | return new Promise((res, rej) => { 100 | Snippet.find({}, function (err, data) { 101 | if (err) { 102 | rej({ 103 | error: true, 104 | connected: false, 105 | data: [], 106 | responseMessage: err 107 | }); 108 | } 109 | returnObj = { 110 | connected: true, 111 | error: false, 112 | responseMessage: successMessage, 113 | data: data 114 | }; 115 | res(returnObj); 116 | }); 117 | }); 118 | }, 119 | setUpSchema: () => { 120 | try { 121 | Snippet = mongoose.model('Snippet'); 122 | } catch (error) { 123 | let Schema = mongoose.Schema; 124 | let snippetSchema = new Schema({ 125 | categories: Array, 126 | snippet: String 127 | }); 128 | Snippet = mongoose.model('Snippet', snippetSchema); 129 | } 130 | return Snippet; 131 | } 132 | } -------------------------------------------------------------------------------- /controllers/json-routes.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | // CRUD routes for JSON file snippets entries. 5 | const self = module.exports = { 6 | jsonFilePath: "", 7 | aliasJsonFilePath: "", 8 | getSnippets: (req,res) => { 9 | console.log("Called GetSnippets!"); 10 | self.jsonFilePath = path.normalize(req.body.databaseUrl); 11 | 12 | //create file if it doesn't exist. 13 | try { 14 | 15 | fs.open(self.jsonFilePath, "wx", function (err, fd) { 16 | if (err) { 17 | // throw(err); 18 | console.log("File exists already"); 19 | } else { 20 | let newJson = [ 21 | { 22 | snippet: "This is an example snippet from a new JSON file. Delete me, create more snippets with cover letter text, and categorize them appropriately!", 23 | categories: ["intro","cover","letter","snippets"] 24 | } 25 | ]; 26 | self.writeJson(newJson, ()=> { 27 | fs.close(fd, function (err) { 28 | if (err) { 29 | console.log("error closing created json file: " + err); 30 | } 31 | }); 32 | }); 33 | } 34 | 35 | }); 36 | } catch(err) { 37 | console.log("Error: Thrown error"); 38 | console.log(err); 39 | } 40 | 41 | self.returnJsonData().then(data => { 42 | let returnObj = { 43 | responseMessage: "Connected to JSON file and Returned Results!", 44 | connected: true, 45 | data: data 46 | }; 47 | res.json(returnObj); 48 | }).catch(err => { 49 | res.status(500).json({ 50 | error: true, 51 | responseMessage: "Sorry, could not connect to JSON file", 52 | connected: false, 53 | data: [] 54 | }); 55 | }); 56 | }, 57 | addSnippet: (req,res) => { 58 | console.log("calling addSnippet"); 59 | const snippet = req.body.snippet; 60 | const categories = req.body.categories; 61 | 62 | 63 | self.returnJsonData().then(data => { 64 | console.log("promise return from addSnippet"); 65 | let db = data; 66 | const snippetObject = { 67 | _id: self.createUniqueId(db), 68 | snippet: snippet, 69 | categories: categories 70 | }; 71 | 72 | db.push(snippetObject); 73 | console.log("db in json routes add snippet: "); 74 | console.log(db); 75 | self.writeJson(db, () => { 76 | console.log("Added snippet:"); 77 | console.log(snippet); 78 | console.log(categories); 79 | res.json(self.createResponseObject(db, "Added Snippet to the Database Successfully!")); 80 | }); 81 | 82 | }).catch(err => { 83 | let returnObj = { 84 | error: true, 85 | responseMessage: err, 86 | data: [], 87 | connected: true 88 | } 89 | res.status(500).json(returnObj); 90 | }); 91 | }, 92 | editSnippet: (req,res) => { 93 | const id = req.body.id; 94 | const snippet = req.body.snippet; 95 | const categories = req.body.categories; 96 | const snippetObject = { 97 | snippet: snippet, 98 | categories: categories 99 | }; 100 | 101 | self.returnJsonData().then(data => { 102 | let db = data; 103 | let foundSnippet = false; 104 | 105 | for(let i = 0; i < db.length; i++) { 106 | if (db[i]._id === id) { 107 | db[i].snippet = snippet; 108 | db[i].categories = categories; 109 | foundSnippet = true; 110 | } 111 | } 112 | 113 | if (foundSnippet) { 114 | self.writeJson(db, ()=> { 115 | res.json(self.createResponseObject(db, "Edited your snipped with an id of: " + id)); 116 | }); 117 | } else { 118 | self.catchError("Could not find snippet with an id of: " + id, res, 400); 119 | } 120 | 121 | }).catch((err) => { 122 | self.catchError(err, res); 123 | }); 124 | }, 125 | deleteSnippet: (req,res) => { 126 | const id = req.body.id; 127 | self.returnJsonData().then(data => { 128 | let db = data; 129 | let foundSnippet = false; 130 | 131 | for (let i = 0; i < db.length; i++) { 132 | if (db[i]._id === id) { 133 | //Splice this element out of the db. 134 | db.splice(i, 1); 135 | foundSnippet = true; 136 | } 137 | } 138 | 139 | if (foundSnippet) { 140 | self.writeJson(db, () => { 141 | res.json(self.createResponseObject(db, "Successfully deleted snippet with Id of "+id)); 142 | }); 143 | } else { 144 | self.catchError("Could not find snippet with an id of: " + id, res, 400); 145 | } 146 | 147 | }).catch(err => { 148 | self.catchError(err,res); 149 | }); 150 | }, 151 | returnJsonData: () => { 152 | return new Promise((response, reject) => { 153 | try { 154 | 155 | const database = require(path.resolve(__dirname, "../", self.jsonFilePath)); 156 | 157 | // console.log("Got JSON DB. Last entry:"); 158 | // console.log(database[database.length-1]._id); 159 | response(database); 160 | } catch (err) { 161 | reject(err); 162 | } 163 | }); 164 | }, 165 | createUniqueId: (db) => { 166 | let newId = Math.floor(Math.random() * 1000000); 167 | for(let i = 0; i < db.length; i++) { 168 | if(db[i]._id === newId) { 169 | return self.createUniqueId(db); 170 | } 171 | } 172 | return newId; 173 | }, 174 | writeJson: (db, callback) => { 175 | let stream = fs.createWriteStream(path.resolve(__dirname, "../", self.jsonFilePath)); 176 | stream.write(JSON.stringify(db), (err) => { 177 | if (err) { 178 | console.log("There was an error writing the file stream!"); 179 | console.error(err); 180 | } 181 | stream.end(); 182 | console.log("Wrote to file successfully!"); 183 | callback(); 184 | }); 185 | // fs.writeFileSync(path.resolve(__dirname, "../", self.jsonFilePath), JSON.stringify(db), (err) => { 186 | // if (err) { 187 | // console.log("Error writing to JSON file!"); 188 | // throw err; 189 | // } 190 | // }); 191 | }, 192 | createResponseObject: (db, successMsg) => { 193 | console.log(successMsg); 194 | return { 195 | error: false, 196 | responseMessage: successMsg, 197 | data: db, 198 | connected: true 199 | }; 200 | }, 201 | catchError: (err, res, status = 500) => { 202 | console.log("Caught Error: "+err); 203 | res.status(status).json({ 204 | error:true, 205 | responseMessage: err, 206 | connected: true, 207 | data: [] 208 | }); 209 | }, 210 | 211 | 212 | // for aliases 213 | getCategoryAliases: (req,res) => { 214 | console.log("Called getCategoryAliases!"); 215 | self.aliasJsonFilePath = path.normalize(req.body.databaseUrl); 216 | console.log("alias json file path: " + self.aliasJsonFilePath); 217 | 218 | //create file if it doesn't exist. 219 | try { 220 | 221 | fs.open(self.aliasJsonFilePath, "wx", function (err, fd) { 222 | if (err) { 223 | // throw(err); 224 | console.log("categoryAliasesFile exists already"); 225 | } else { 226 | let newJson = [ 227 | { 228 | category: "category1", 229 | aliases: ["alias1","alias2","alias3","alias4"] 230 | } 231 | ]; 232 | self.writeCategoryAliasesToJson(newJson, ()=> { 233 | fs.close(fd, function (err) { 234 | if (err) { 235 | console.log("error closing created json category aliases file: " + err); 236 | } 237 | }); 238 | }); 239 | } 240 | 241 | }); 242 | } catch(err) { 243 | console.log("Error: Thrown error"); 244 | console.log(err); 245 | } 246 | 247 | self.returnJsonCategoryAliasesData().then(data => { 248 | console.log("my alias data: "); 249 | console.log(data); 250 | let returnObj = { 251 | responseMessage: "Connected to JSON category aliases file and Returned Results!", 252 | connected: true, 253 | data: data 254 | }; 255 | res.json(returnObj); 256 | }).catch(err => { 257 | res.status(500).json({ 258 | error: true, 259 | responseMessage: "Sorry, could not connect to JSON category aliases file", 260 | connected: false, 261 | data: [] 262 | }); 263 | }); 264 | }, 265 | addCategoryAliases: (req,res) => { 266 | console.log("calling addCategoryAliases"); 267 | const category = req.body.category; 268 | const aliases = req.body.aliases; 269 | 270 | 271 | self.returnJsonCategoryAliasesData().then(data => { 272 | console.log("promise return from addCategoryAliases"); 273 | let db = data; 274 | const categoryAliasesObj = { 275 | _id: self.createUniqueCategoryAliasId(db), 276 | category: category, 277 | aliases: aliases 278 | }; 279 | 280 | db.push(categoryAliasesObj); 281 | 282 | self.writeCategoryAliasesToJson(db, () => { 283 | console.log("Added category and aliases:"); 284 | console.log(category); 285 | console.log(aliases); 286 | res.json(self.createResponseCategoryAliasesObject(db, "Added category and aliases to the Database Successfully!")); 287 | }); 288 | 289 | }).catch(err => { 290 | let returnObj = { 291 | error: true, 292 | responseMessage: err, 293 | data: [], 294 | connected: true 295 | } 296 | res.status(500).json(returnObj); 297 | }); 298 | }, 299 | editCategoryAliases: (req,res) => { 300 | const id = req.body.id; 301 | const category = req.body.category; 302 | const aliases = req.body.aliases; 303 | const categoryAliasesObj = { 304 | category: category, 305 | aliases: aliases 306 | }; 307 | 308 | self.returnJsonCategoryAliasesData().then(data => { 309 | let db = data; 310 | let foundCategory = false; 311 | 312 | for(let i = 0; i < db.length; i++) { 313 | if (db[i]._id === id) { 314 | db[i].category = category; 315 | db[i].aliases = aliases; 316 | foundCategory = true; 317 | } 318 | } 319 | 320 | if (foundCategory) { 321 | self.writeCategoryAliasesToJson(db, ()=> { 322 | res.json(self.createResponseCategoryAliasesObject(db, "Edited your category with an id of: " + id)); 323 | }); 324 | } else { 325 | self.catchCategoryAliasesError("Could not find category with an id of: " + id, res, 400); 326 | } 327 | 328 | }).catch((err) => { 329 | self.catchCategoryAliasesError(err, res); 330 | }); 331 | }, 332 | deleteCategoryAliases: (req,res) => { 333 | const id = req.body.id; 334 | self.returnJsonCategoryAliasesData().then(data => { 335 | let db = data; 336 | let foundCategory = false; 337 | 338 | for (let i = 0; i < db.length; i++) { 339 | if (db[i]._id === id) { 340 | //Splice this element out of the db. 341 | db.splice(i, 1); 342 | foundCategory = true; 343 | } 344 | } 345 | 346 | if (foundCategory) { 347 | self.writeCategoryAliasesToJson(db, () => { 348 | res.json(self.createResponseCategoryAliasesObject(db, "Successfully deleted category with Id of "+id)); 349 | }); 350 | } else { 351 | self.catchCategoryAliasesError("Could not find category with an id of: " + id, res, 400); 352 | } 353 | 354 | }).catch(err => { 355 | self.catchCategoryAliasesError(err,res); 356 | }); 357 | }, 358 | returnJsonCategoryAliasesData: () => { 359 | return new Promise((response, reject) => { 360 | try { 361 | 362 | const database = require(path.resolve(__dirname, "../", self.aliasJsonFilePath)); 363 | 364 | // console.log("Got JSON DB. Last entry:"); 365 | // console.log(database[database.length-1]._id); 366 | response(database); 367 | } catch (err) { 368 | reject(err); 369 | } 370 | }); 371 | }, 372 | createUniqueCategoryAliasId: (db) => { 373 | let newId = Math.floor(Math.random() * 1000000); 374 | for(let i = 0; i < db.length; i++) { 375 | if(db[i]._id === newId) { 376 | return self.createUniqueCategoryAliasId(db); 377 | } 378 | } 379 | return newId; 380 | }, 381 | writeCategoryAliasesToJson: (db, callback) => { 382 | let stream = fs.createWriteStream(path.resolve(__dirname, "../", self.aliasJsonFilePath)); 383 | stream.write(JSON.stringify(db), (err) => { 384 | if (err) { 385 | console.log("There was an error writing the file stream!"); 386 | console.error(err); 387 | } 388 | stream.end(); 389 | console.log("Wrote to file successfully!"); 390 | callback(); 391 | }); 392 | // fs.writeFileSync(path.resolve(__dirname, "../", self.aliasJsonFilePath), JSON.stringify(db), (err) => { 393 | // if (err) { 394 | // console.log("Error writing to JSON file!"); 395 | // throw err; 396 | // } 397 | // }); 398 | }, 399 | createResponseCategoryAliasesObject: (db, successMsg) => { 400 | console.log(successMsg); 401 | return { 402 | error: false, 403 | responseMessage: successMsg, 404 | data: db, 405 | connected: true 406 | }; 407 | }, 408 | catchCategoryAliasesError: (err, res, status = 500) => { 409 | console.log("Caught Error: "+err); 410 | res.status(status).json({ 411 | error:true, 412 | responseMessage: err, 413 | connected: true, 414 | data: [] 415 | }); 416 | } 417 | } -------------------------------------------------------------------------------- /dist/assets/sakura-dark.css: -------------------------------------------------------------------------------- 1 | /* $color-text: #dedce5; */ 2 | /* Sakura.css v1.0.0 3 | * ================ 4 | * Minimal css theme. 5 | * Project: https://github.com/oxalorg/sakura 6 | */ 7 | /* Body */ 8 | html { 9 | font-size: 62.5%; 10 | font-family: serif; } 11 | 12 | body { 13 | font-size: 1.8rem; 14 | line-height: 1.618; 15 | max-width: 38em; 16 | margin: auto; 17 | color: #c9c9c9; 18 | background-color: #222222; 19 | padding: 13px; } 20 | 21 | @media (max-width: 684px) { 22 | body { 23 | font-size: 1.53rem; } } 24 | 25 | @media (max-width: 382px) { 26 | body { 27 | font-size: 1.35rem; } } 28 | 29 | h1, h2, h3, h4, h5, h6 { 30 | line-height: 1.1; 31 | font-family: Verdana, Geneva, sans-serif; 32 | font-weight: 700; 33 | overflow-wrap: break-word; 34 | word-wrap: break-word; 35 | -ms-word-break: break-all; 36 | word-break: break-word; 37 | -ms-hyphens: auto; 38 | -moz-hyphens: auto; 39 | -webkit-hyphens: auto; 40 | hyphens: auto; } 41 | 42 | h1 { 43 | font-size: 2.35em; } 44 | 45 | h2 { 46 | font-size: 2.00em; } 47 | 48 | h3 { 49 | font-size: 1.75em; } 50 | 51 | h4 { 52 | font-size: 1.5em; } 53 | 54 | h5 { 55 | font-size: 1.25em; } 56 | 57 | h6 { 58 | font-size: 1em; } 59 | 60 | small, sub, sup { 61 | font-size: 75%; } 62 | 63 | hr { 64 | border-color: #ffffff; } 65 | 66 | a { 67 | text-decoration: none; 68 | color: #ffffff; } 69 | a:hover { 70 | color: #c9c9c9; 71 | border-bottom: 2px solid #c9c9c9; } 72 | 73 | ul { 74 | padding-left: 1.4em; } 75 | 76 | li { 77 | margin-bottom: 0.4em; } 78 | 79 | blockquote { 80 | font-style: italic; 81 | margin-left: 1.5em; 82 | padding-left: 1em; 83 | border-left: 3px solid #ffffff; } 84 | 85 | img { 86 | max-width: 100%; } 87 | 88 | /* Pre and Code */ 89 | pre { 90 | background-color: #4a4a4a; 91 | display: block; 92 | padding: 1em; 93 | overflow-x: auto; } 94 | 95 | code { 96 | font-size: 0.9em; 97 | padding: 0 0.5em; 98 | background-color: #4a4a4a; 99 | white-space: pre-wrap; } 100 | 101 | pre > code { 102 | padding: 0; 103 | background-color: transparent; 104 | white-space: pre; } 105 | 106 | /* Tables */ 107 | table { 108 | text-align: justify; 109 | width: 100%; 110 | border-collapse: collapse; } 111 | 112 | td, th { 113 | padding: 0.5em; 114 | border-bottom: 1px solid #4a4a4a; } 115 | 116 | /* Buttons, forms and input */ 117 | input, textarea { 118 | border: 1px solid #c9c9c9; } 119 | input:focus, textarea:focus { 120 | border: 1px solid #ffffff; } 121 | 122 | textarea { 123 | width: 100%; } 124 | 125 | .button, button, input[type="submit"], input[type="reset"], input[type="button"] { 126 | display: inline-block; 127 | padding: 5px 10px; 128 | text-align: center; 129 | text-decoration: none; 130 | white-space: nowrap; 131 | background-color: #ffffff; 132 | color: #222222; 133 | border-radius: 1px; 134 | border: 1px solid #ffffff; 135 | cursor: pointer; 136 | box-sizing: border-box; } 137 | .button[disabled], button[disabled], input[type="submit"][disabled], input[type="reset"][disabled], input[type="button"][disabled] { 138 | cursor: default; 139 | opacity: .5; } 140 | .button:focus, .button:hover, button:focus, button:hover, input[type="submit"]:focus, input[type="submit"]:hover, input[type="reset"]:focus, input[type="reset"]:hover, input[type="button"]:focus, input[type="button"]:hover { 141 | background-color: #c9c9c9; 142 | border-color: #c9c9c9; 143 | color: #222222; 144 | outline: 0; } 145 | 146 | textarea, select, input[type] { 147 | color: #c9c9c9; 148 | padding: 6px 10px; 149 | /* The 6px vertically centers text on FF, ignored by Webkit */ 150 | margin-bottom: 10px; 151 | background-color: #4a4a4a; 152 | border: 1px solid #4a4a4a; 153 | border-radius: 4px; 154 | box-shadow: none; 155 | box-sizing: border-box; } 156 | textarea:focus, select:focus, input[type]:focus { 157 | border: 1px solid #ffffff; 158 | outline: 0; } 159 | 160 | input[type="checkbox"]:focus { 161 | outline: 1px dotted #ffffff; } 162 | 163 | label, legend, fieldset { 164 | display: block; 165 | margin-bottom: .5rem; 166 | font-weight: 600; } 167 | -------------------------------------------------------------------------------- /dist/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattcheah/cover-letter-snippets/c9d863fe638cdd6c997751fd59f45331883979b2/dist/favicon.ico -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Cover Letter Snippets 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /dist/runtime.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // install a JSONP callback for chunk loading 3 | /******/ function webpackJsonpCallback(data) { 4 | /******/ var chunkIds = data[0]; 5 | /******/ var moreModules = data[1]; 6 | /******/ var executeModules = data[2]; 7 | /******/ // add "moreModules" to the modules object, 8 | /******/ // then flag all "chunkIds" as loaded and fire callback 9 | /******/ var moduleId, chunkId, i = 0, resolves = []; 10 | /******/ for(;i < chunkIds.length; i++) { 11 | /******/ chunkId = chunkIds[i]; 12 | /******/ if(installedChunks[chunkId]) { 13 | /******/ resolves.push(installedChunks[chunkId][0]); 14 | /******/ } 15 | /******/ installedChunks[chunkId] = 0; 16 | /******/ } 17 | /******/ for(moduleId in moreModules) { 18 | /******/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) { 19 | /******/ modules[moduleId] = moreModules[moduleId]; 20 | /******/ } 21 | /******/ } 22 | /******/ if(parentJsonpFunction) parentJsonpFunction(data); 23 | /******/ while(resolves.length) { 24 | /******/ resolves.shift()(); 25 | /******/ } 26 | /******/ 27 | /******/ // add entry modules from loaded chunk to deferred list 28 | /******/ deferredModules.push.apply(deferredModules, executeModules || []); 29 | /******/ 30 | /******/ // run deferred modules when all chunks ready 31 | /******/ return checkDeferredModules(); 32 | /******/ }; 33 | /******/ function checkDeferredModules() { 34 | /******/ var result; 35 | /******/ for(var i = 0; i < deferredModules.length; i++) { 36 | /******/ var deferredModule = deferredModules[i]; 37 | /******/ var fulfilled = true; 38 | /******/ for(var j = 1; j < deferredModule.length; j++) { 39 | /******/ var depId = deferredModule[j]; 40 | /******/ if(installedChunks[depId] !== 0) fulfilled = false; 41 | /******/ } 42 | /******/ if(fulfilled) { 43 | /******/ deferredModules.splice(i--, 1); 44 | /******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]); 45 | /******/ } 46 | /******/ } 47 | /******/ return result; 48 | /******/ } 49 | /******/ 50 | /******/ // The module cache 51 | /******/ var installedModules = {}; 52 | /******/ 53 | /******/ // object to store loaded and loading chunks 54 | /******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched 55 | /******/ // Promise = chunk loading, 0 = chunk loaded 56 | /******/ var installedChunks = { 57 | /******/ "runtime": 0 58 | /******/ }; 59 | /******/ 60 | /******/ var deferredModules = []; 61 | /******/ 62 | /******/ // The require function 63 | /******/ function __webpack_require__(moduleId) { 64 | /******/ 65 | /******/ // Check if module is in cache 66 | /******/ if(installedModules[moduleId]) { 67 | /******/ return installedModules[moduleId].exports; 68 | /******/ } 69 | /******/ // Create a new module (and put it into the cache) 70 | /******/ var module = installedModules[moduleId] = { 71 | /******/ i: moduleId, 72 | /******/ l: false, 73 | /******/ exports: {} 74 | /******/ }; 75 | /******/ 76 | /******/ // Execute the module function 77 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 78 | /******/ 79 | /******/ // Flag the module as loaded 80 | /******/ module.l = true; 81 | /******/ 82 | /******/ // Return the exports of the module 83 | /******/ return module.exports; 84 | /******/ } 85 | /******/ 86 | /******/ 87 | /******/ // expose the modules object (__webpack_modules__) 88 | /******/ __webpack_require__.m = modules; 89 | /******/ 90 | /******/ // expose the module cache 91 | /******/ __webpack_require__.c = installedModules; 92 | /******/ 93 | /******/ // define getter function for harmony exports 94 | /******/ __webpack_require__.d = function(exports, name, getter) { 95 | /******/ if(!__webpack_require__.o(exports, name)) { 96 | /******/ Object.defineProperty(exports, name, { 97 | /******/ configurable: false, 98 | /******/ enumerable: true, 99 | /******/ get: getter 100 | /******/ }); 101 | /******/ } 102 | /******/ }; 103 | /******/ 104 | /******/ // define __esModule on exports 105 | /******/ __webpack_require__.r = function(exports) { 106 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); 107 | /******/ }; 108 | /******/ 109 | /******/ // getDefaultExport function for compatibility with non-harmony modules 110 | /******/ __webpack_require__.n = function(module) { 111 | /******/ var getter = module && module.__esModule ? 112 | /******/ function getDefault() { return module['default']; } : 113 | /******/ function getModuleExports() { return module; }; 114 | /******/ __webpack_require__.d(getter, 'a', getter); 115 | /******/ return getter; 116 | /******/ }; 117 | /******/ 118 | /******/ // Object.prototype.hasOwnProperty.call 119 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 120 | /******/ 121 | /******/ // __webpack_public_path__ 122 | /******/ __webpack_require__.p = ""; 123 | /******/ 124 | /******/ var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || []; 125 | /******/ var oldJsonpFunction = jsonpArray.push.bind(jsonpArray); 126 | /******/ jsonpArray.push = webpackJsonpCallback; 127 | /******/ jsonpArray = jsonpArray.slice(); 128 | /******/ for(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]); 129 | /******/ var parentJsonpFunction = oldJsonpFunction; 130 | /******/ 131 | /******/ 132 | /******/ // run deferred modules from other chunks 133 | /******/ checkDeferredModules(); 134 | /******/ }) 135 | /************************************************************************/ 136 | /******/ ([]); 137 | //# sourceMappingURL=runtime.js.map -------------------------------------------------------------------------------- /dist/runtime.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack:///webpack/bootstrap"],"names":[],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAQ,oBAAoB;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,yBAAiB,4BAA4B;AAC7C;AACA;AACA,0BAAkB,2BAA2B;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA,yDAAiD,cAAc;AAC/D;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA;AACA;AACA;AACA,wBAAgB,uBAAuB;AACvC;;;AAGA;AACA","file":"runtime.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tfunction webpackJsonpCallback(data) {\n \t\tvar chunkIds = data[0];\n \t\tvar moreModules = data[1];\n \t\tvar executeModules = data[2];\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [];\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(data);\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n\n \t\t// add entry modules from loaded chunk to deferred list\n \t\tdeferredModules.push.apply(deferredModules, executeModules || []);\n\n \t\t// run deferred modules when all chunks ready\n \t\treturn checkDeferredModules();\n \t};\n \tfunction checkDeferredModules() {\n \t\tvar result;\n \t\tfor(var i = 0; i < deferredModules.length; i++) {\n \t\t\tvar deferredModule = deferredModules[i];\n \t\t\tvar fulfilled = true;\n \t\t\tfor(var j = 1; j < deferredModule.length; j++) {\n \t\t\t\tvar depId = deferredModule[j];\n \t\t\t\tif(installedChunks[depId] !== 0) fulfilled = false;\n \t\t\t}\n \t\t\tif(fulfilled) {\n \t\t\t\tdeferredModules.splice(i--, 1);\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = deferredModule[0]);\n \t\t\t}\n \t\t}\n \t\treturn result;\n \t}\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// object to store loaded and loading chunks\n \t// undefined = chunk not loaded, null = chunk preloaded/prefetched\n \t// Promise = chunk loading, 0 = chunk loaded\n \tvar installedChunks = {\n \t\t\"runtime\": 0\n \t};\n\n \tvar deferredModules = [];\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \tvar jsonpArray = window[\"webpackJsonp\"] = window[\"webpackJsonp\"] || [];\n \tvar oldJsonpFunction = jsonpArray.push.bind(jsonpArray);\n \tjsonpArray.push = webpackJsonpCallback;\n \tjsonpArray = jsonpArray.slice();\n \tfor(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);\n \tvar parentJsonpFunction = oldJsonpFunction;\n\n\n \t// run deferred modules from other chunks\n \tcheckDeferredModules();\n"],"sourceRoot":""} -------------------------------------------------------------------------------- /dist/styles.js: -------------------------------------------------------------------------------- 1 | (window["webpackJsonp"] = window["webpackJsonp"] || []).push([["styles"],{ 2 | 3 | /***/ "./node_modules/raw-loader/index.js!./node_modules/postcss-loader/lib/index.js??embedded!./src/assets/sakura-dark.css": 4 | /*!**********************************************************************************************************!*\ 5 | !*** ./node_modules/raw-loader!./node_modules/postcss-loader/lib??embedded!./src/assets/sakura-dark.css ***! 6 | \**********************************************************************************************************/ 7 | /*! no static exports found */ 8 | /***/ (function(module, exports) { 9 | 10 | module.exports = "/* $color-text: #dedce5; */\r\n/* Sakura.css v1.0.0\r\n * ================\r\n * Minimal css theme.\r\n * Project: https://github.com/oxalorg/sakura\r\n */\r\n/* Body */\r\nhtml {\r\n font-size: 62.5%;\r\n font-family: serif; }\r\nbody {\r\n font-size: 1.8rem;\r\n line-height: 1.618;\r\n max-width: 38em;\r\n margin: auto;\r\n color: #c9c9c9;\r\n background-color: #222222;\r\n padding: 13px; }\r\n@media (max-width: 684px) {\r\n body {\r\n font-size: 1.53rem; } }\r\n@media (max-width: 382px) {\r\n body {\r\n font-size: 1.35rem; } }\r\nh1, h2, h3, h4, h5, h6 {\r\n line-height: 1.1;\r\n font-family: Verdana, Geneva, sans-serif;\r\n font-weight: 700;\r\n overflow-wrap: break-word;\r\n word-wrap: break-word;\r\n -ms-word-break: break-all;\r\n word-break: break-word;\r\n -ms-hyphens: auto;\r\n -webkit-hyphens: auto;\r\n hyphens: auto; }\r\nh1 {\r\n font-size: 2.35em; }\r\nh2 {\r\n font-size: 2.00em; }\r\nh3 {\r\n font-size: 1.75em; }\r\nh4 {\r\n font-size: 1.5em; }\r\nh5 {\r\n font-size: 1.25em; }\r\nh6 {\r\n font-size: 1em; }\r\nsmall, sub, sup {\r\n font-size: 75%; }\r\nhr {\r\n border-color: #ffffff; }\r\na {\r\n text-decoration: none;\r\n color: #ffffff; }\r\na:hover {\r\n color: #c9c9c9;\r\n border-bottom: 2px solid #c9c9c9; }\r\nul {\r\n padding-left: 1.4em; }\r\nli {\r\n margin-bottom: 0.4em; }\r\nblockquote {\r\n font-style: italic;\r\n margin-left: 1.5em;\r\n padding-left: 1em;\r\n border-left: 3px solid #ffffff; }\r\nimg {\r\n max-width: 100%; }\r\n/* Pre and Code */\r\npre {\r\n background-color: #4a4a4a;\r\n display: block;\r\n padding: 1em;\r\n overflow-x: auto; }\r\ncode {\r\n font-size: 0.9em;\r\n padding: 0 0.5em;\r\n background-color: #4a4a4a;\r\n white-space: pre-wrap; }\r\npre > code {\r\n padding: 0;\r\n background-color: transparent;\r\n white-space: pre; }\r\n/* Tables */\r\ntable {\r\n text-align: justify;\r\n width: 100%;\r\n border-collapse: collapse; }\r\ntd, th {\r\n padding: 0.5em;\r\n border-bottom: 1px solid #4a4a4a; }\r\n/* Buttons, forms and input */\r\ninput, textarea {\r\n border: 1px solid #c9c9c9; }\r\ninput:focus, textarea:focus {\r\n border: 1px solid #ffffff; }\r\ntextarea {\r\n width: 100%; }\r\n.button, button, input[type=\"submit\"], input[type=\"reset\"], input[type=\"button\"] {\r\n display: inline-block;\r\n padding: 5px 10px;\r\n text-align: center;\r\n text-decoration: none;\r\n white-space: nowrap;\r\n background-color: #ffffff;\r\n color: #222222;\r\n border-radius: 1px;\r\n border: 1px solid #ffffff;\r\n cursor: pointer;\r\n box-sizing: border-box; }\r\n.button[disabled], button[disabled], input[type=\"submit\"][disabled], input[type=\"reset\"][disabled], input[type=\"button\"][disabled] {\r\n cursor: default;\r\n opacity: .5; }\r\n.button:focus, .button:hover, button:focus, button:hover, input[type=\"submit\"]:focus, input[type=\"submit\"]:hover, input[type=\"reset\"]:focus, input[type=\"reset\"]:hover, input[type=\"button\"]:focus, input[type=\"button\"]:hover {\r\n background-color: #c9c9c9;\r\n border-color: #c9c9c9;\r\n color: #222222;\r\n outline: 0; }\r\ntextarea, select, input[type] {\r\n color: #c9c9c9;\r\n padding: 6px 10px;\r\n /* The 6px vertically centers text on FF, ignored by Webkit */\r\n margin-bottom: 10px;\r\n background-color: #4a4a4a;\r\n border: 1px solid #4a4a4a;\r\n border-radius: 4px;\r\n box-shadow: none;\r\n box-sizing: border-box; }\r\ntextarea:focus, select:focus, input[type]:focus {\r\n border: 1px solid #ffffff;\r\n outline: 0; }\r\ninput[type=\"checkbox\"]:focus {\r\n outline: 1px dotted #ffffff; }\r\nlabel, legend, fieldset {\r\n display: block;\r\n margin-bottom: .5rem;\r\n font-weight: 600; }\r\n" 11 | 12 | /***/ }), 13 | 14 | /***/ "./node_modules/raw-loader/index.js!./node_modules/postcss-loader/lib/index.js??embedded!./src/styles.css": 15 | /*!**********************************************************************************************!*\ 16 | !*** ./node_modules/raw-loader!./node_modules/postcss-loader/lib??embedded!./src/styles.css ***! 17 | \**********************************************************************************************/ 18 | /*! no static exports found */ 19 | /***/ (function(module, exports) { 20 | 21 | module.exports = "/* You can add global styles to this file, and also import other style files */\r\n\r\nbody {\r\n padding: 13px 13px 80px 13px !important;\r\n}\r\n\r\na {\r\n color: #b0ccea;\r\n}\r\n\r\n.flex {\r\n display:flex;\r\n justify-content: space-around;\r\n flex-wrap: wrap;\r\n}\r\n\r\n.table-container {\r\n max-height:400px;\r\n overflow-y:scroll;\r\n margin-bottom:30px;\r\n border-radius: 5px;\r\n}\r\n\r\ntable {\r\n font-size:11px;\r\n font-family:sans-serif;\r\n}\r\n\r\ntable thead tr {\r\n background-color:#171717;\r\n}\r\n\r\ntable thead td{\r\n font-size:14px;\r\n color:white;\r\n}\r\n\r\ntable thead tr {\r\n max-height:100px;\r\n}\r\n\r\ntable td {\r\n word-wrap: break-word;\r\n word-break: break-all;\r\n}\r\n\r\ntable td a {\r\n cursor:pointer;\r\n}\r\n\r\ntable tbody tr:nth-child(2n) {\r\n background-color:#333;\r\n}\r\n\r\ntable tbody tr:nth-child(2n+1) {\r\n background-color:#2A2A2A;\r\n}\r\n\r\n.line-break {\r\n margin:10px auto;\r\n width: 80%;\r\n border-bottom:1px solid #c9c9c9;\r\n}\r\n" 22 | 23 | /***/ }), 24 | 25 | /***/ "./node_modules/style-loader/lib/addStyles.js": 26 | /*!****************************************************!*\ 27 | !*** ./node_modules/style-loader/lib/addStyles.js ***! 28 | \****************************************************/ 29 | /*! no static exports found */ 30 | /***/ (function(module, exports, __webpack_require__) { 31 | 32 | /* 33 | MIT License http://www.opensource.org/licenses/mit-license.php 34 | Author Tobias Koppers @sokra 35 | */ 36 | 37 | var stylesInDom = {}; 38 | 39 | var memoize = function (fn) { 40 | var memo; 41 | 42 | return function () { 43 | if (typeof memo === "undefined") memo = fn.apply(this, arguments); 44 | return memo; 45 | }; 46 | }; 47 | 48 | var isOldIE = memoize(function () { 49 | // Test for IE <= 9 as proposed by Browserhacks 50 | // @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805 51 | // Tests for existence of standard globals is to allow style-loader 52 | // to operate correctly into non-standard environments 53 | // @see https://github.com/webpack-contrib/style-loader/issues/177 54 | return window && document && document.all && !window.atob; 55 | }); 56 | 57 | var getTarget = function (target) { 58 | return document.querySelector(target); 59 | }; 60 | 61 | var getElement = (function (fn) { 62 | var memo = {}; 63 | 64 | return function(target) { 65 | // If passing function in options, then use it for resolve "head" element. 66 | // Useful for Shadow Root style i.e 67 | // { 68 | // insertInto: function () { return document.querySelector("#foo").shadowRoot } 69 | // } 70 | if (typeof target === 'function') { 71 | return target(); 72 | } 73 | if (typeof memo[target] === "undefined") { 74 | var styleTarget = getTarget.call(this, target); 75 | // Special case to return head of iframe instead of iframe itself 76 | if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) { 77 | try { 78 | // This will throw an exception if access to iframe is blocked 79 | // due to cross-origin restrictions 80 | styleTarget = styleTarget.contentDocument.head; 81 | } catch(e) { 82 | styleTarget = null; 83 | } 84 | } 85 | memo[target] = styleTarget; 86 | } 87 | return memo[target] 88 | }; 89 | })(); 90 | 91 | var singleton = null; 92 | var singletonCounter = 0; 93 | var stylesInsertedAtTop = []; 94 | 95 | var fixUrls = __webpack_require__(/*! ./urls */ "./node_modules/style-loader/lib/urls.js"); 96 | 97 | module.exports = function(list, options) { 98 | if (typeof DEBUG !== "undefined" && DEBUG) { 99 | if (typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment"); 100 | } 101 | 102 | options = options || {}; 103 | 104 | options.attrs = typeof options.attrs === "object" ? options.attrs : {}; 105 | 106 | // Force single-tag solution on IE6-9, which has a hard limit on the # of