diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..1a6bd45
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+package-lock.json binary
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e7ea1e8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,117 @@
+## Node
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+
+# Diagnostic reports (https://nodejs.org/api/report.html)
+report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
+
+# 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
+*.lcov
+
+# nyc test coverage
+.nyc_output
+
+# Grunt intermediate storage (https://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/
+
+# Snowpack dependency directory (https://snowpack.dev/)
+web_modules/
+
+# TypeScript cache
+*.tsbuildinfo
+
+# Optional npm cache directory
+.npm
+
+# Optional eslint cache
+.eslintcache
+
+# Microbundle cache
+.rpt2_cache/
+.rts2_cache_cjs/
+.rts2_cache_es/
+.rts2_cache_umd/
+
+# Optional REPL history
+.node_repl_history
+
+# Output of 'npm pack'
+*.tgz
+
+# Yarn Integrity file
+.yarn-integrity
+
+# dotenv environment variables file
+.env
+.env.test
+
+# parcel-bundler cache (https://parceljs.org/)
+.cache
+.parcel-cache
+
+# Next.js build output
+.next
+out
+
+# Nuxt.js build / generate output
+.nuxt
+dist
+
+# Gatsby files
+.cache/
+# Comment in the public line in if your project uses Gatsby and not Next.js
+# https://nextjs.org/blog/next-9-1#public-directory-support
+# public
+
+# vuepress build output
+.vuepress/dist
+
+# Serverless directories
+.serverless/
+
+# FuseBox cache
+.fusebox/
+
+# DynamoDB Local files
+.dynamodb/
+
+# TernJS port file
+.tern-port
+
+# Stores VSCode versions used for testing VSCode extensions
+.vscode-test
+
+# yarn v2
+
+.yarn/cache
+.yarn/unplugged
+.yarn/build-state.yml
+.pnp.*
diff --git a/Gruntfile.js b/Gruntfile.js
new file mode 100644
index 0000000..acad4ee
--- /dev/null
+++ b/Gruntfile.js
@@ -0,0 +1,112 @@
+const path = require("path");
+
+module.exports = grunt => {
+ grunt.initConfig({
+ pkg: grunt.file.readJSON("package.json"),
+ clean: {
+ default: ["dist/"],
+ },
+ copy: {
+ html: {
+ files: [{expand: true, cwd: "src/main/", src: "**/*.html", dest: "dist/"}]
+ },
+ },
+ focus: {
+ dev: {
+ include: ["html", "js", "link"],
+ },
+ },
+ replace: {
+ dev: {
+ src: ["./dist/*.html", "./dist/*.js"],
+ replacements: [
+ {
+ from: "%%VERSION_NUMBER%%",
+ to: "<%= pkg.version %>+" + new Date().toISOString().slice(0, 19).replace(/[-:T]/g, "")
+ }
+ ],
+ overwrite: true
+ },
+ deploy: {
+ src: ["./dist/*.html", "./dist/*.js"],
+ replacements: [
+ {
+ from: "%%VERSION_NUMBER%%",
+ to: "<%= pkg.version %>"
+ }
+ ],
+ overwrite: true
+ },
+ },
+ watch: {
+ html: {
+ files: ["src/main/**/*.html"],
+ tasks: ["copy:html"],
+ },
+ js: {
+ files: ["src/main/**/*.js"],
+ tasks: ["webpack:dev", "replace:dev"],
+ },
+ link: {
+ files: ["node_modules/@fwdekker/*/dist/**"],
+ tasks: ["webpack:dev", "replace:dev"],
+ },
+ },
+ webpack: {
+ options: {
+ entry: "./src/main/js/index.js",
+ module: {
+ rules: [
+ {
+ test: /\.js$/,
+ exclude: /node_modules/,
+ },
+ ],
+ },
+ resolve: {
+ extensions: [".js"],
+ },
+ output: {
+ filename: "bundle.js",
+ path: path.resolve(__dirname, "dist/"),
+ },
+ },
+ dev: {
+ mode: "development",
+ devtool: "inline-source-map",
+ },
+ deploy: {
+ mode: "production",
+ },
+ },
+ });
+
+ grunt.loadNpmTasks("grunt-contrib-clean");
+ grunt.loadNpmTasks("grunt-contrib-copy");
+ grunt.loadNpmTasks("grunt-contrib-watch");
+ grunt.loadNpmTasks("grunt-focus");
+ grunt.loadNpmTasks("grunt-text-replace");
+ grunt.loadNpmTasks("grunt-webpack");
+
+ grunt.registerTask("dev", [
+ // Pre
+ "clean",
+ // Copy files
+ "copy:html",
+ // Compile JS
+ "webpack:dev",
+ "replace:dev",
+ ]);
+ grunt.registerTask("dev:server", ["dev", "focus:dev"]);
+ grunt.registerTask("deploy", [
+ // Pre
+ "clean",
+ // Copy files
+ "copy:html",
+ // Compile JS
+ "webpack:deploy",
+ "replace:deploy",
+ ]);
+
+ grunt.registerTask("default", ["dev"]);
+};
diff --git a/README.md b/README.md
index ad814f9..9f2462b 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,23 @@
# Codsworth name generator
Choose a fitting name for your _Fallout 4_ character that Codsworth can pronounce.
This tool gives you a list of names that look like yours so that you can pretend he's saying the right name.
+
+## Development
+### Requirements
+* [npm](https://www.npmjs.com/)
+
+### Setting up
+```shell script
+# Install dependencies (only needed once)
+$> npm ci
+```
+
+### Building
+```shell script
+# Build the tool in `dist/` for development
+$> npm run dev
+# Same as above, but automatically rerun it whenever files are changed
+$> npm run dev:server
+# Build the tool in `dist/` for deployment
+$> npm run deploy
+```
diff --git a/index.html b/index.html
deleted file mode 100644
index b2ff4ee..0000000
--- a/index.html
+++ /dev/null
@@ -1,248 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Codsworth name generator
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Similar names
-
-
-
Random names
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..cb6b70d
Binary files /dev/null and b/package-lock.json differ
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..3fc849e
--- /dev/null
+++ b/package.json
@@ -0,0 +1,33 @@
+{
+ "name": "codsworth-namegen",
+ "version": "1.1.0",
+ "description": "Choose a fitting name for your Fallout 4 character that Codsworth can pronounce",
+ "author": "Felix W. Dekker",
+ "browser": "dist/bundle.js",
+ "repository": {
+ "type": "git",
+ "url": "git@git.fwdekker.com:FWDekker/codsworth-namegen.git"
+ },
+ "private": true,
+ "scripts": {
+ "clean": "grunt clean",
+ "dev": "grunt dev",
+ "dev:server": "grunt dev:server",
+ "deploy": "grunt deploy"
+ },
+ "dependencies": {
+ "@fwdekker/template": "^0.0.21"
+ },
+ "devDependencies": {
+ "grunt": "^1.2.1",
+ "grunt-cli": "^1.3.2",
+ "grunt-contrib-clean": "^2.0.0",
+ "grunt-contrib-copy": "^1.0.0",
+ "grunt-contrib-watch": "^1.1.0",
+ "grunt-focus": "^1.0.0",
+ "grunt-text-replace": "^0.4.0",
+ "grunt-webpack": "^4.0.2",
+ "webpack": "^4.44.0",
+ "webpack-cli": "^3.3.12"
+ }
+}
diff --git a/src/main/index.html b/src/main/index.html
new file mode 100644
index 0000000..aaac8a2
--- /dev/null
+++ b/src/main/index.html
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+ Codsworth name generator
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Similar names
+
+
+
Random names
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/js/index.js b/src/main/js/index.js
new file mode 100644
index 0000000..dd3c700
--- /dev/null
+++ b/src/main/js/index.js
@@ -0,0 +1,160 @@
+import {$, doAfterLoad, footer, header, nav} from "@fwdekker/template";
+import {jaro_winkler} from "./jaro-winkler";
+
+
+/// Constants
+const similarCount = 25;
+const randomCount = 25;
+const nameList = ["Aaliyah", "Aaron", "Abigail", "Abram", "Abrams", "Adalyn", "Adam", "Adams", "Addison", "Adeline", "Adrian", "Ahn", "Aideen", "Aiden", "Akira", "Al", "Alaina", "Alan", "Alana", "Alex", "Alexander", "Alexandra", "Alexis", "Alice", "Allen", "Allison", "Altman", "Alyssa", "Amanda", "Amelia", "Anderson", "Andonov", "Andrew", "Andy", "Angel", "Angela", "Anna", "Annabelle", "Anthony", "Archer", "Aria", "Arianna", "Asdf", "Ash", "Asher", "Ashford", "Ashley", "Asimov", "Assface", "Atkins", "Atkinson", "Atom", "Atomic", "Atticus", "Aubrey", "Audrey", "Austin", "Autumn", "Ava", "Avery", "Bacon", "Badass", "Bailey", "Baker", "Banner", "Bannerman", "Bannion", "Barnes", "Barron", "Barry", "Bash", "Bastard", "Battosai", "Batty", "Baudoin", "Bell", "Bella", "Ben", "Benjamin", "Bennell", "Bennett", "Bentley", "Bery", "Bill", "Billy", "Bilodeau", "Black", "Blaise", "Blake", "Blaze", "Bob", "Bobbi", "Bobby", "Bogdanove", "Bond", "Boob", "Boobie", "Boobies", "Boom", "Boston", "Bowman", "Bradley", "Braun", "Brayden", "Brenda", "Brenna", "Brian", "Brianna", "Brick", "Brigner", "Brock", "Brody", "Brooklyn", "Brooks", "Browder", "Brown", "Browne", "Bruce", "Bruckheimer", "Bryan", "Bryant", "Buffy", "Bulger", "Bull", "Burgess", "Burke", "Burt", "Butch", "Butler", "Caden", "Cal", "Caleb", "Callie", "Camden", "Camilla", "Campbell", "Capable", "Carey", "Carnow", "Carofano", "Caroline", "Carson", "Carter", "Carver", "Casserly", "Castle", "Catherine", "Cha", "Chapin", "Chappy", "Charles", "Charlie", "Charlotte", "Chase", "Cheng", "Cherise", "Cherry", "CherryBomb", "Chloe", "Chopper", "Chris", "Christian", "Christiane", "Christopher", "Church", "Claire", "Clara", "Clark", "Clarke", "Claw", "Clemens", "Clunk", "Cobb", "Cobra", "Cock", "Cockerham", "Cole", "Colin", "Collins", "Colton", "Conall", "Connor", "Cook", "Cooke", "Cooper", "Cormac", "Corman", "Cornelius", "Cornett", "Corrie", "Corrine", "Corvo", "Corwin", "Cory", "Cosgrove", "Courtenay", "Courtney", "Cox", "Coyle", "Craig", "Crash", "Cruz", "Cubbison", "Cullen", "Cummings", "Dag", "Damien", "Dan", "Dane", "Danger", "Daniel", "Daniels", "Danny", "Darrel", "Darren", "Darryl", "Daryl", "Dave", "David", "Davis", "Dawson", "Deag", "Death", "Deb", "Debbie", "Deborah", "Deckard", "Declan", "Deitrick", "Delaney", "Dell", "Dennis", "Denton", "Deschain", "Deth", "Diana", "Diane", "DiAngelo", "Diaz", "Dick", "DiMaggio", "Dinolt", "DJ", "Django", "Dom", "Domics", "Dominguez", "Dominic", "Don", "Donald", "Dong", "DongJun", "Donnie", "Donny", "Doug", "Douglas", "Dragon", "Draper", "Dulany", "Dutch", "Duvall", "Dylan", "Eagle", "East", "Ed", "Eddie", "Eddy", "Edwards", "Elena", "Eli", "Eliana", "Elijah", "Elizabeth", "Ella", "Ellie", "Elliot", "Elliott", "Emil", "Emile", "Emily", "Emma", "Erectus", "Eric", "Erik", "Erin", "Ernest", "Ernie", "Ethan", "Eugene", "Eva", "Evan", "Evans", "Evelyn", "Everdeen", "Everett", "Felipe", "Ferret", "Fifi", "Finn", "Finster", "Fiona", "Fisher", "Flag", "Flagg", "Flash", "Flores", "Flynn", "Foster", "Fox", "Fragile", "Francis", "Franke", "Freeman", "Frost", "Fuck", "Fucker", "Fuckface", "Furiosa", "Fury", "Gabriel", "Gabriella", "Gardiner", "Gary", "Gavin", "Gene", "George", "Georgia", "Gerry", "Gianna", "Gil", "Glen", "Gomez", "Gonzalez", "Goose", "Gordon", "Graber", "Grace", "Grant", "Gravato", "Gray", "Grayson", "Greco", "Green", "Greene", "Grey", "Griffin", "Grognak", "Gryphon", "Gutierrez", "Guy", "Hackman", "Hailey", "Hall", "Ham", "Hamilton", "Hamm", "Hammer", "Hammett", "Hamrick", "Han", "Hannah", "Hans", "Harden", "Hardi", "Harold", "Harper", "Harris", "Harry", "Haschart", "Hasenbuhler", "Hastings", "Hawk", "Hawke", "Hazel", "Henning", "Henry", "Herbert", "Hicks", "Hill", "Hines", "Holly", "Holmes", "Hook", "Hopgood", "Houle", "Howard", "Hudson", "Hughes", "Humongous", "Humungus", "Hyun", "Ian", "Ilya", "Imperator", "Indiana", "Indy", "Isaac", "Isabella", "Isabelle", "Isaiah", "Ist", "Istvan", "J.P.", "Jack", "Jackson", "Jacob", "Jag", "Jake", "James", "Jangjoon", "Jasmine", "Jason", "Jay", "Jayce", "Jayden", "Jeff", "Jeffery", "Jen", "Jenkins", "Jennifer", "Jeremiah", "Jeremy", "Jerry", "Jerusalem", "Jess", "Jessica", "Jessie", "Jet", "Jim", "Jimmy", "Joan", "Joe", "Joel", "Joey", "John", "Johnson", "Jon", "Jonathan", "Jones", "JonPaul", "Jordan", "Jordyn", "Joseph", "Josh", "Joshua", "Josiah", "JP", "Juan", "Julia", "Julian", "Juliana", "Justin", "Kaela", "Kaelyn", "Kaitlyn", "Kal", "KalEl", "Kaneda", "Kate", "Katharine", "Katherine", "Katniss", "Kauffman", "Kayla", "Kaylee", "Keira", "Kelley", "Kelly", "Kelvin", "Ken", "Kennedy", "Kenshin", "Kevin", "Kim", "King", "Kirk", "Knight", "Krietz", "Kuhlmann", "Kurt", "Kylie", "Lafferty", "Lamb", "Landon", "Lane", "Langlois", "Laura", "Lauren", "Laurie", "Layla", "Lea", "Leah", "Lederer", "Lee", "Leo", "Leon", "Les", "Leslie", "Levi", "Lewis", "Li", "Liam", "Liesegang", "Lila", "Liliana", "Lillian", "Lily", "Lincoln", "Linda", "Lionheart", "Lipari", "Liz", "Logan", "London", "Loner", "Long", "Lopez", "Losi", "Lucas", "Luce", "Lucy", "Luke", "Lundin", "Lupe", "Lynda", "Maam", "Mackenzie", "Macklin", "Madam", "Madeleine", "Madelyn", "Madison", "Makayla", "Mal", "Malcolm", "Mamba", "Mandy", "Mara", "Marcus", "Marge", "Maria", "Marie", "Marji", "Marjorie", "Mark", "Markiepoo", "Marko", "Markus", "Marlowe", "Marsden", "Martin", "Martinez", "Marty", "Mary", "Mason", "Mateo", "Matt", "Matthew", "Matty", "Max", "Maya", "McCoy", "McDyer", "McFly", "McKay", "McPherson", "Means", "Megan", "Meister", "Mejillones", "Mia", "Micah", "Michael", "Michonne", "Miguel", "Mikami", "Mike", "Mila", "Miles", "Miller", "Mitchell", "Mohammed", "Molly", "Monster", "Montana", "Moonves", "Moore", "Morales", "Morgan", "Morgue", "Morpheus", "Morris", "Muck", "Mudguts", "Muhammad", "Mulder", "Muldoon", "Murphy", "Myers", "Nadia", "Nancy", "Nanes", "Nardone", "Nasty", "Natalia", "Natalie", "Natasha", "Nate", "Nathan", "Nathaniel", "Nazarov", "nchez", "Neary", "Nelson", "Neo", "Nesmith", "Neville", "Nguyen", "Nicholas", "Nico", "Nipple", "Noah", "Nogueira", "Nolan", "Noonan", "Nora", "Norm", "Norm", "Norman", "Normand", "North", "Northup", "Nourmohammadi", "Nuclear", "Nuke", "Olds", "Oliver", "Olivia", "Ollie", "Olsen", "Olson", "Optical", "Orgasmo", "Orin", "Ortiz", "Owen", "Owens", "Pagliarulo", "Palmer", "Paris", "Parker", "Parson", "Pat", "Patrick", "Patty", "Paul", "Pely", "Pendleton", "Penelope", "Perez", "Perry", "Pete", "Peter", "Peterson", "Peyton", "Phil", "Philip", "Phillips", "Picard", "Plissken", "Powell", "Preacher", "Price", "Priest", "Prince", "Princess", "Psycho", "Puma", "Purkey", "Purkeypile", "Python", "Qin", "Quartermain", "Quatermass", "Queen", "Quinn", "Rabil", "Raf", "Rafael", "Ramirez", "Ramsey", "Randal", "Randall", "Rankin", "Rapp", "Ray", "Raymond", "Reagan", "Red", "Reed", "Reese", "Rex", "Reyes", "Reynolds", "Ricardo", "Richard", "Richards", "Richardson", "Rick", "Ricky", "Rictus", "Riddick", "Riley", "Ripken", "Ripley", "River", "Rivera", "Rob", "Robb", "Robert", "Roberts", "Robinson", "Rock", "Rockatansky", "Rocky", "Rodriguez", "Roger", "Rogers", "Roland", "Rollins", "Romanov", "Romanova", "Romero", "Ron", "Ronald", "Ronnie", "Ronny", "Rook", "Rosa", "Rose", "Ross", "Roy", "Ruby", "Russell", "Ryan", "Sadie", "Sage", "Salvatore", "Sam", "Samantha", "Sammie", "Sammy", "Samuel", "Sanchez", "Sanders", "Sandra", "Sanjuro", "Sara", "Sarah", "Sarse", "Savannah", "Sawyer", "Scarlett", "Schaefer", "Scharf", "Schram", "Schreiber", "Scott", "Scully", "Sears", "Sebastian", "Selena", "Seljenes", "Serena", "Seth", "Sex", "Sexy", "Shane", "Shannon", "Sheiman", "Shen", "Shinji", "Shrike", "Sidney", "Simmons", "Singer", "Sir", "Skyler", "Slaughter", "Slinger", "Slit", "Sloan", "Smirnova", "Smith", "Snake", "Snow", "Snyder", "Solo", "Solomon", "Sophia", "Sophie", "South", "Southie", "Spade", "Spider", "Spike", "Splendid", "Spring", "Springsteen", "Stark", "Stef", "Stella", "Steph", "Stephanie", "Stephen", "Sterling", "Steve", "Steven", "Steward", "Stewart", "Stone", "Struthers", "Stuart", "Sullivan", "Summer", "Sunshine", "Sweetpea", "Sydney", "Tallahassee", "Taylor", "Teare", "Ted", "Teddy", "Teitel", "Tesla", "Tetsuo", "Texas", "Thomas", "Thompson", "Thorn", "Thorne", "Tiana", "Tim", "Timmy", "Timothy", "Tit", "Tittie", "Titties", "Toadie", "Toast", "Todd", "Toecutter", "Tom", "Tommy", "Tonon", "Tony", "Torres", "Tracey", "Tracy", "Treadway", "Tresnjak", "Trinity", "Tristan", "Trump", "Tuck", "Turner", "Tyler", "Unbreakable", "Utting", "Valenti", "Valentina", "Valkyrie", "Vargas", "Vash", "Venkman", "Vic", "Vicens", "Victoria", "Violet", "Vivian", "Vlatko", "Wagner", "Walker", "Walton", "Wanderer", "Ward", "Washington", "Watson", "Watts", "Wayne", "Webb", "Wells", "Wes", "West", "Weyland", "Wez", "White", "Whitey", "Wikus", "Will", "William", "Williams", "Willy", "Wilson", "Winter", "Wisnewski", "Wood", "Woodward", "Wright", "Wyatt", "Xavier", "Yan", "Yojimbo", "Yorick", "Young", "Yutani", "Zachary", "Zdana", "Zed", "Zenith", "Zetta", "Ziggy", "Zip", "Zoe"];
+
+
+/// Shared functions
+// Returns a mod b
+const modulo = (a, b) => (((a % b) + b) % b);
+
+
+/// Name generator
+class Name {
+ constructor(size) {
+ size = (size === undefined ? 10 : size);
+
+ this.count_ = 0;
+ this.history_ = [];
+ this.size_ = size;
+ }
+
+
+ // Returns a random name
+ static generate_() {
+ return nameList[Math.floor(Math.random() * nameList.length)];
+ }
+
+ // Adds given name to history
+ add(name) {
+ if (name !== undefined) {
+ this.history_[modulo(this.count_, this.size_)] = name;
+ this.count_++;
+ }
+
+ return name;
+ }
+
+ // Adds a random name to history
+ addRandom() {
+ return this.add(Name.generate_());
+ };
+
+ // Returns history
+ getHistory(separator, count) {
+ count = (count === undefined ? Math.min(this.size_, this.count_) : count);
+
+ const out = [];
+ for (let i = count; i > 0; i--) {
+ const name = this.history_[modulo((this.count_ - i), this.size_)];
+ if (name === undefined)
+ break;
+
+ out.push(name);
+ }
+
+ return out.join(separator);
+ };
+}
+
+
+/// Jaro-Winkler similarity
+class JaroWinkler {
+ constructor(name) {
+ this.algo_ = jaro_winkler;
+ this.name_ = name;
+
+ this.reset_();
+ this.populate_();
+ }
+
+
+ // Comparator for values returned by algorithm
+ static comparator_(a, b) {
+ return b[1] - a[1];
+ }
+
+ // Resets object
+ reset_() {
+ this.hits_ = [];
+ };
+
+ // Populates hits
+ populate_() {
+ const listSize = nameList.length;
+
+ for (let i = 0; i < listSize; i++) {
+ const name = nameList[i];
+ const value = this.algo_(this.name_, name, {caseSensitive: false});
+
+ this.hits_[i] = [name, value];
+ }
+
+ this.hits_.sort(JaroWinkler.comparator_);
+ };
+
+ // Returns `amount` best matches
+ getSimilar(amount) {
+ const similar = [];
+
+ for (let i = 0; i < amount; i++)
+ similar[i] = this.hits_[i][0];
+
+ return similar;
+ };
+}
+
+
+/// Setup
+// Load template
+doAfterLoad(() => {
+ $("#nav").appendChild(nav("/Tools/Codsworth Name Generator"));
+ $("#header").appendChild(header({
+ title: "Codsworth Name Generator",
+ description: `Choose a fitting name for your Fallout 4 character that Codsworth can pronounce`
+ }));
+ $("#footer").appendChild(footer({
+ author: "Felix W. Dekker",
+ authorURL: "https://fwdekker.com/",
+ license: "MIT License",
+ licenseURL: "https://git.fwdekker.com/FWDekker/codsworth-namegen/src/branch/master/LICENSE",
+ vcs: "git",
+ vcsURL: "https://git.fwdekker.com/FWDekker/codsworth-namegen/",
+ version: "v%%VERSION_NUMBER%%"
+ }));
+ $("main").style.display = null;
+});
+
+// Event handlers
+doAfterLoad(() => {
+ const generateSimilar = () => {
+ const name = $("#similarInput").value;
+ if (name === undefined || name === "")
+ return;
+
+ const names = (new JaroWinkler(name)).getSimilar(similarCount);
+ $("#similarNames").value = names.join("\n");
+ };
+
+ $("#generateSimilar").onclick = generateSimilar;
+ $("#similarInput").addEventListener("keypress", e => {
+ if (e.key === "Enter") {
+ generateSimilar();
+ e.preventDefault();
+ }
+ });
+
+
+ const randNamer = new Name(randomCount);
+ $("#generateRandom").onclick = () => {
+ randNamer.addRandom();
+
+ const randOutput = $("#randomNames");
+ randOutput.value = randNamer.getHistory("\n");
+ randOutput.scrollTop = randOutput.scrollHeight;
+ };
+});
diff --git a/jaro-winkler.js b/src/main/js/jaro-winkler.js
similarity index 92%
rename from jaro-winkler.js
rename to src/main/js/jaro-winkler.js
index 45a2724..d61b068 100644
--- a/jaro-winkler.js
+++ b/src/main/js/jaro-winkler.js
@@ -24,7 +24,15 @@
"use strict";
-const jaro_winkler = function (a, b, options) {
+const optionDefault = (template, options) => {
+ for (let prop in options)
+ if (options.hasOwnProperty(prop))
+ template[prop] = options[prop];
+
+ return template;
+};
+
+export const jaro_winkler = function (a, b, options) {
// Load default options
options = optionDefault({"caseSensitive": true}, options);