Compare commits

...

2 Commits
master ... main

Author SHA1 Message Date
06cb7c6ede Update README 2024-10-15 16:40:06 -04:00
6f41b9d5be Library updates 2024-10-15 16:37:26 -04:00
17 changed files with 2110 additions and 469 deletions

View File

@ -4,37 +4,36 @@ The Codex Mythica is a database of all of the cards released for the Mythic Wars
## Installing ## Installing
+ Requires: [git](https://git-scm.com/), [Node](https://nodejs.org/), [Express](https://expressjs.com/), and (optionally) a static web server (we recommend [nginx](https://nginx.org/)). - Requires: [git](https://git-scm.com/), [Node](https://nodejs.org/), [Express](https://expressjs.com/), and (optionally) a static web server (we recommend [nginx](https://nginx.org/)).
+ Clone from the git repo: - Clone from the git repo:
```shell ```shell
git clone https://git.itsericwoodward.com/eric/codex-mythica.git mwg-codex git clone https://git.itsericwoodward.com/eric/codex-mythica.git
``` ```
+ Go into the directory for the site: - Go into the directory for the site:
```shell ```shell
cd mwg-codex cd codex-mythica
``` ```
+ Install the required NPM libraries: - Install the required NPM libraries:
```shell ```shell
npm install npm install
``` ```
+ Launch the production binary file: - Launch the production binary file:
```shell ```shell
./bin/www-prod ./bin/www-prod
``` ```
+ Share and enjoy! - Share and enjoy!
## License ## License
The cards and images from the game are copyright (c) 2014-2018 Eric Woodward, all rights reserved. The cards and images from the game are copyright (c) 2014-2024 Eric Woodward, all rights reserved.
The rest of the project is copyright (c) 2017-2018 Eric Woodward, released under the MIT license. The rest of the project is copyright (c) 2017-2024 Eric Woodward, released under the MIT license.

82
app.js
View File

@ -1,40 +1,48 @@
var var express = require("express"),
express = require('express'), path = require("path"),
path = require('path'), logger = require("morgan"),
logger = require('morgan'), cookieParser = require("cookie-parser"),
cookieParser = require('cookie-parser'), compression = require("compression"),
bodyParser = require('body-parser'), routes = require("./routes/index"),
compression = require('compression'), search = require("./routes/search"),
pkg = require("./package"),
routes = require('./routes/index'),
search = require('./routes/search'),
pkg = require('./package'),
app = express(); app = express();
Object.assign( Object.assign(app.locals, {
app.locals, { mw_site_uri: "https://mythicwarsgame.com",
mw_site_uri: 'https://mythicwarsgame.com',
site: { site: {
title: 'The Codex Mythica', title: "The Codex Mythica",
description: "The Codex Mythica is a database of all of the cards released for the Mythic Wars card game. Browse through all of the cards in the game, or search to find the card(s) you're looking for.", description:
keywords: 'codex, card game, mythic cards, mythic wars cards, mythic wars, clash of the gods, cthulhu rises, nemesis, excalibre, collectible card game, ccg, mythic sets, game, multiplayer, hobby, zeus, thor', "The Codex Mythica is a database of all of the cards released for the Mythic Wars card game. Browse through all of the cards in the game, or search to find the card(s) you're looking for.",
base_uri: (process.env.NODE_ENV || '').toLowerCase().indexOf('dev') > -1 ? 'http://localhost:8320' : 'https://codex.mythicwarsgame.com' keywords:
"codex, card game, mythic cards, mythic wars cards, mythic wars, clash of the gods, cthulhu rises, nemesis, excalibre, collectible card game, ccg, mythic sets, game, multiplayer, hobby, zeus, thor",
base_uri:
(process.env.NODE_ENV || "").toLowerCase().indexOf("dev") > -1
? "http://localhost:8320"
: "https://codex.mythicwarsgame.com",
}, },
author: { author: {
name: pkg.author.name, name: pkg.author.name,
contact: pkg.author.email contact: pkg.author.email,
} },
}); });
// view engine setup // view engine setup
app.set('views', path.join(__dirname, 'views')); app.set("views", path.join(__dirname, "views"));
// app.set('view engine', 'jade'); // app.set('view engine', 'jade');
app.set('view engine', 'ejs'); app.set("view engine", "ejs");
app.use(logger(':req[x-forwarded-for] - [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length]')); app.use(
app.use(bodyParser.json()); logger(
app.use(bodyParser.urlencoded()); ':req[x-forwarded-for] - [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length]'
)
);
app.use(express.json());
app.use(
express.urlencoded({
extended: true,
})
);
app.use(cookieParser()); app.use(cookieParser());
app.use((req, res, next) => { app.use((req, res, next) => {
@ -44,26 +52,28 @@ app.use((req, res, next) => {
next(); next();
}); });
app.use(compression()); app.use(compression());
app.use('/', routes); app.use("/", routes);
app.use('/search/', search); app.use("/search/", search);
app.use(express.static(path.join(__dirname, 'public'))); app.use(express.static(path.join(__dirname, "public")));
/// catch 404 and forwarding to error handler /// catch 404 and forwarding to error handler
app.use(function (req, res, next) { app.use(function (req, res, next) {
res.status(404).sendFile(path.join(__dirname + '/public/errors', '404.html')); res.status(404).sendFile(
path.join(__dirname + "/public/errors", "404.html")
);
}); });
/// error handlers /// error handlers
// development error handler // development error handler
// will print stacktrace // will print stacktrace
if ((process.env.NODE_ENV || '').toLowerCase().indexOf('dev') > -1 ) { if ((process.env.NODE_ENV || "").toLowerCase().indexOf("dev") > -1) {
app.use(function (err, req, res, next) { app.use(function (err, req, res, next) {
res.status(err.status || 500); res.status(err.status || 500);
res.render('error', { res.render("error", {
message: err.message, message: err.message,
error: err error: err,
}); });
}); });
} }
@ -72,12 +82,10 @@ if ((process.env.NODE_ENV || '').toLowerCase().indexOf('dev') > -1 ) {
// no stacktraces leaked to user // no stacktraces leaked to user
app.use(function (err, req, res, next) { app.use(function (err, req, res, next) {
res.status(err.status || 500); res.status(err.status || 500);
res.render('error', { res.render("error", {
message: err.message, message: err.message,
error: {} error: {},
}); });
}); });
module.exports = app; module.exports = app;

10
bin/www
View File

@ -1,9 +1,9 @@
#!/usr/bin/node #!/usr/bin/node
var debug = require('debug')('my-application'); var debug = require("debug")("my-application");
var app = require('../app'); var app = require("../app");
app.set('port', process.env.PORT || 8320); app.set("port", process.env.PORT || 8320);
var server = app.listen(app.get('port'), function() { const server = app.listen(app.get("port"), () => {
console.log('Express server listening on port ' + server.address().port); console.log("Express server listening on port " + server.address().port);
}); });

File diff suppressed because it is too large Load Diff

1637
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,18 @@
{ {
"name": "@mysticbits/codex-mythica", "name": "@itsericwoodward/codex-mythica",
"version": "0.4.0", "version": "0.6.1",
"private": true, "private": true,
"scripts": { "scripts": {
"start": "nodejs ./bin/www" "start": "nodejs ./bin/www"
}, },
"dependencies": { "dependencies": {
"body-parser": "~1.0.0", "body-parser": "~1.20.3",
"compression": "^1.7.1", "compression": "^1.7.4",
"cookie-parser": "~1.0.1", "cookie-parser": "~1.4.7",
"debug": "~0.7.4", "debug": "~4.3.7",
"ejs": "^2.5.7", "ejs": "^3.1.10",
"express": "~4.16.0", "express": "~4.21.1",
"morgan": "~1.0.0" "morgan": "~1.10.0"
}, },
"author": { "author": {
"name": "Eric Woodward", "name": "Eric Woodward",
@ -20,6 +20,6 @@
"url": "https://itsericwoodward.com/" "url": "https://itsericwoodward.com/"
}, },
"devDependencies": { "devDependencies": {
"ejs-lint": "^0.3.0" "ejs-lint": "^2.0.0"
} }
} }

View File

@ -101,7 +101,7 @@ body {
background: url('/images/tile-bg.jpg'); background: url('/images/tile-bg.jpg');
color: #FFFDD7; color: #FFFDD7;
font-family: 'liberation_serif', serif; font-family: 'liberation_serif', serif;
font-size: 12pt; font-size: 14pt;
line-height: 1.35em; line-height: 1.35em;
} }
@ -206,9 +206,6 @@ p {
line-height: 1.35em; line-height: 1.35em;
} }
.card-info > img {
}
.card-pantheon { .card-pantheon {
max-width: 1.1em; max-width: 1.1em;
vertical-align: middle; vertical-align: middle;
@ -346,10 +343,6 @@ p {
border-radius: 0.6em; border-radius: 0.6em;
} }
.navMenu {
}
.navMenu ul { .navMenu ul {
list-style-type: none; list-style-type: none;
margin: 0; margin: 0;
@ -684,39 +677,15 @@ p {
max-height: 10em; /* just in case */ max-height: 10em; /* just in case */
} }
.js.js-hasFontsLoaded body { .js.js-hasFontsLoaded body {
font-size: 14pt; font-size: 16pt;
} }
/*
* Didn't use this, saving it unless I decie to use it later.
.js .js-ulToggle {
cursor: pointer;
}
.js .js-ulToggle::after {
content: ' \25BC';
font-size: .5em;
vertical-align: text-top;
}
.js .js-ulToggle-hidden ul {
display: none;
}
.js .js-ulToggle-hidden .js-ulToggle::after {
content: ' \25B2';
}
*/
/**************************************************************************** /****************************************************************************
* Responsive Media Queries * Responsive Media Queries
****************************************************************************/ ****************************************************************************/
@media screen and (min-width: 30em) {
@media screen and (min-width: 32em) {
.dataBox { .dataBox {
display: grid; display: grid;
@ -738,15 +707,9 @@ p {
} }
} }
@media screen and (min-width: 33em) {
.dataBox {
grid-template-columns: repeat(auto-fill, minmax(6em, 1fr)) ;
}
}
@media screen and (min-width: 37em) { @media screen and (min-width: 37em) {
.dataBox { .dataBox {
grid-template-columns: repeat(auto-fill, minmax(7em, 1fr)) ; grid-template-columns: repeat(auto-fill, minmax(6em, 1fr)) ;
} }
} }
@ -767,6 +730,12 @@ p {
} }
} }
@media screen and (min-width: 42em) {
.dataBox {
grid-template-columns: repeat(auto-fill, minmax(7em, 1fr)) ;
}
}
@media screen and (min-width: 58em) { @media screen and (min-width: 58em) {
.card-data { .card-data {
grid-column: auto / span 2; grid-column: auto / span 2;
@ -775,12 +744,11 @@ p {
} }
.card-image { .card-image {
display: block; display: block;
width: auto;
} }
.card-info { .card-info {
align-items: center; align-items: center;
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, minmax(12em, 1fr)) ; grid-template-columns: repeat(auto-fill, minmax(13em, 1fr)) ;
} }
.dataBox { .dataBox {
grid-template-columns: repeat(auto-fill, minmax(8em, 1fr)) ; grid-template-columns: repeat(auto-fill, minmax(8em, 1fr)) ;

View File

@ -1,15 +1,13 @@
'use strict'; "use strict";
const const express = require("express"),
express = require('express'),
sortByName = function (list) { sortByName = function (list) {
let let coll_opts = {
coll_opts = { sensitivity: "accent",
sensitivity: 'accent',
numeric: true, numeric: true,
caseFirst: "upper" caseFirst: "upper",
}, },
field = 'name', field = "name",
coll = new Intl.Collator({}, coll_opts); coll = new Intl.Collator({}, coll_opts);
list.sort((a, b) => { list.sort((a, b) => {
if (a[field] && b[field]) { if (a[field] && b[field]) {
@ -22,36 +20,52 @@ const
let router = express.Router(); let router = express.Router();
/* GET home page. */ /* GET home page. */
router.get('/', function(req, res) { router.get("/", function (req, res) {
let let cards = require("../lib/cards.json"),
cards = require('../lib/cards.json'), rand_card_num = Math.floor(
rand_card_num = Math.floor(Math.random() * Math.floor(cards.length-1)); Math.random() * Math.floor(cards.length - 1)
);
res.render('index', { title: 'Welcome', query: (req.query || {}), card: cards[rand_card_num], random_num: rand_card_num }); res.render("index", {
title: "Welcome",
query: req.query || {},
card: cards[rand_card_num],
random_num: rand_card_num,
});
}); });
router.get('/cards/:card_num', (req, res) => { router.get("/cards/:card_num", (req, res) => {
req.params.card_num = (req.params.card_num || 'all'); req.params.card_num = req.params.card_num || "all";
let let cards = require("../lib/cards.json"),
cards = require('../lib/cards.json'), links = require("../lib/links.json"),
links = require('../lib/links.json'), filtered = cards.filter(
filtered = cards.filter(card => (card) =>
card.num.toLowerCase().indexOf(req.params.card_num.toLowerCase()) > -1 || req.params.card_num.toLowerCase() === 'all' card.num
.toLowerCase()
.indexOf(req.params.card_num.toLowerCase()) > -1 ||
req.params.card_num.toLowerCase() === "all"
); );
if (filtered.length === 1) { if (filtered.length === 1) {
let card = filtered[0]; let card = filtered[0];
if (links && card.hasOwnProperty('name') && links.hasOwnProperty(card.name)) { if (
links &&
card.hasOwnProperty("name") &&
links.hasOwnProperty(card.name)
) {
Object.assign(card, links[card.name]); Object.assign(card, links[card.name]);
} }
res.render('single', { title: card.name + ' (' + card.num + ')', card: card }); res.render("single", {
title: card.name + " (" + card.num + ")",
card: card,
});
} else { } else {
filtered = sortByName(filtered); filtered = sortByName(filtered);
res.render('all', { title: 'All Cards', cards: filtered }); res.render("all", { title: "All Cards", cards: filtered });
} }
}); });
router.get('/cards', function(req, res) { router.get("/cards", function (req, res) {
res.redirect('/cards/all'); res.redirect("/cards/all");
}); });
module.exports = router; module.exports = router;

View File

@ -1,23 +1,25 @@
'use strict'; "use strict";
const express = require("express"),
const
express = require('express'),
sortByField = function (field, order, list) { sortByField = function (field, order, list) {
field = (field || 'num'); field = field || "num";
order = (order || 'asc'); order = order || "asc";
let let coll_opts = {
coll_opts = { sensitivity: "accent",
sensitivity: 'accent',
numeric: true, numeric: true,
caseFirst: "upper" caseFirst: "upper",
}, },
coll = new Intl.Collator({}, coll_opts); coll = new Intl.Collator({}, coll_opts);
list.sort((a, b) => { list.sort((a, b) => {
if (a[field] && b[field]) { if (a[field] && b[field]) {
let res = coll.compare(a[field], b[field]) * (order !== 'asc' ? -1 : 1); let res =
if (res === 0 && field !== 'name') { coll.compare(a[field], b[field]) *
return coll.compare(a['name'], b['name']) * (order !== 'asc' ? -1 : 1); (order !== "asc" ? -1 : 1);
if (res === 0 && field !== "name") {
return (
coll.compare(a["name"], b["name"]) *
(order !== "asc" ? -1 : 1)
);
} }
return res; return res;
} }
@ -29,44 +31,51 @@ const
let router = express.Router(); let router = express.Router();
/* GET search results page. */ /* GET search results page. */
router.get('/', function(req, res) { router.get("/", function (req, res) {
req.query = req.query || {}; req.query = req.query || {};
let filtered = []; let filtered = [];
if (Object.keys(req.query).length > 0) { if (Object.keys(req.query).length > 0) {
let let q = req.query,
q = req.query, cards = require("../lib/cards.json");
cards = require('../lib/cards.json');
q.search_in = (q.search_in || []); q.search_in = q.search_in || [];
q.search_for = (q.search_for || '').trim().toLowerCase(); q.search_for = (q.search_for || "").trim().toLowerCase();
q.pantheons = (q.pantheons || []); q.pantheons = q.pantheons || [];
q.pantheons = Array.isArray(q.pantheons) ? q.pantheons : [q.pantheons]; q.pantheons = Array.isArray(q.pantheons) ? q.pantheons : [q.pantheons];
q.elements = (q.elements || []); q.elements = q.elements || [];
q.elements = Array.isArray(q.elements) ? q.elements : [q.elements]; q.elements = Array.isArray(q.elements) ? q.elements : [q.elements];
q.types = (q.types || []); q.types = q.types || [];
q.types = Array.isArray(q.types) ? q.types : [q.types]; q.types = Array.isArray(q.types) ? q.types : [q.types];
q.races = (q.races || []); q.races = q.races || [];
q.races = Array.isArray(q.races) ? q.races : [q.races]; q.races = Array.isArray(q.races) ? q.races : [q.races];
q.releases = (q.releases || []); q.releases = q.releases || [];
q.releases = Array.isArray(q.releases) ? q.releases : [q.releases]; q.releases = Array.isArray(q.releases) ? q.releases : [q.releases];
q.sort_by = (q.sort_by || 'num').trim().toLowerCase(); q.sort_by = (q.sort_by || "num").trim().toLowerCase();
q.sort_order = (q.sort_order || 'asc').trim().toLowerCase(); q.sort_order = (q.sort_order || "asc").trim().toLowerCase();
console.log(`sort_by: ${q.sort_by}`); filtered = cards.filter((card) => {
if (q.search_in.length > 0 && q.search_for.trim() !== "") {
filtered = cards.filter(card => { if (
!(
if (q.search_in.length > 0 && q.search_for.trim() !== '') { (q.search_in.indexOf("name") > -1 &&
if (!( (card.name.toLowerCase().indexOf(q.search_for) >
(q.search_in.indexOf('name') > -1 && (card.name.toLowerCase().indexOf(q.search_for) > -1 || card.name_ang.indexOf(q.search_for) > -1)) || -1 ||
(q.search_in.indexOf('ability') > -1 && (card.ability_name.toLowerCase().indexOf(q.search_for) > -1 || card.ability_text.toLowerCase().indexOf(q.search_for) > -1)))) { card.name_ang.indexOf(q.search_for) > -1)) ||
(q.search_in.indexOf("ability") > -1 &&
(card.ability_name
.toLowerCase()
.indexOf(q.search_for) > -1 ||
card.ability_text
.toLowerCase()
.indexOf(q.search_for) > -1))
)
) {
return false; return false;
} }
} }
if (q.pantheons.length > 0 && card.pantheon) { if (q.pantheons.length > 0 && card.pantheon) {
let let has_pantheon = false;
has_pantheon = false;
for (let i = 0; i < q.pantheons.length; i++) { for (let i = 0; i < q.pantheons.length; i++) {
if (card.pantheon_idx.indexOf(q.pantheons[i]) > -1) { if (card.pantheon_idx.indexOf(q.pantheons[i]) > -1) {
has_pantheon = true; has_pantheon = true;
@ -78,8 +87,7 @@ router.get('/', function(req, res) {
} }
if (q.elements.length > 0) { if (q.elements.length > 0) {
let let has_element = false;
has_element = false;
for (let i = 0; i < q.elements.length; i++) { for (let i = 0; i < q.elements.length; i++) {
if (card.element_idx.indexOf(q.elements[i]) > -1) { if (card.element_idx.indexOf(q.elements[i]) > -1) {
has_element = true; has_element = true;
@ -91,8 +99,7 @@ router.get('/', function(req, res) {
} }
if (q.races.length > 0 && card.race) { if (q.races.length > 0 && card.race) {
let let has_race = false;
has_race = false;
for (let i = 0; i < q.races.length; i++) { for (let i = 0; i < q.races.length; i++) {
if (card.race_idx.indexOf(q.races[i]) > -1) { if (card.race_idx.indexOf(q.races[i]) > -1) {
has_race = true; has_race = true;
@ -104,8 +111,7 @@ router.get('/', function(req, res) {
} }
if (q.types.length > 0) { if (q.types.length > 0) {
let let has_type = false;
has_type = false;
for (let i = 0; i < q.types.length; i++) { for (let i = 0; i < q.types.length; i++) {
if (card.type_idx.indexOf(q.types[i]) > -1) { if (card.type_idx.indexOf(q.types[i]) > -1) {
has_type = true; has_type = true;
@ -117,8 +123,7 @@ router.get('/', function(req, res) {
} }
if (q.releases.length > 0) { if (q.releases.length > 0) {
let let has_release = false;
has_release = false;
for (let i = 0; i < q.releases.length; i++) { for (let i = 0; i < q.releases.length; i++) {
if (card.num.toLowerCase().indexOf(q.releases[i]) > -1) { if (card.num.toLowerCase().indexOf(q.releases[i]) > -1) {
has_release = true; has_release = true;
@ -131,13 +136,17 @@ router.get('/', function(req, res) {
return true; return true;
}); });
if (q.sort_by !== 'name') { if (q.sort_by !== "name") {
filtered = sortByField('name', q.sort_order, filtered); filtered = sortByField("name", q.sort_order, filtered);
} }
filtered = sortByField(q.sort_by, q.sort_order, filtered); filtered = sortByField(q.sort_by, q.sort_order, filtered);
} }
res.render('search', { title:`Search Results (${filtered.length})`, query: req.query, cards: filtered }); res.render("search", {
title: `Search Results (${filtered.length})`,
query: req.query,
cards: filtered,
});
}); });
module.exports = router; module.exports = router;

View File

@ -1,19 +1,19 @@
<!-- views/pages/index.ejs --> <!-- views/pages/index.ejs -->
<% include ./partials/top %> <%- include('./partials/top') %>
<body class="container"> <body class="container">
<% include ./partials/header %> <%- include('./partials/header') %>
<main class='main'> <main class='main'>
<% include ./partials/cards %> <%- include('./partials/cards') %>
</main> </main>
<% include ./partials/footer %> <%- include('./partials/footer') %>
<% include ./partials/scripts %> <%- include('./partials/scripts') %>
</body> </body>
</html> </html>

View File

@ -24,7 +24,7 @@
</main> </main>
<footer> <footer>
<% include ./partials/footer %> <% include('./partials/footer') %>
</footer> </footer>
</body> </body>

View File

@ -1,25 +1,30 @@
<!-- views/pages/index.ejs --> <!-- views/pages/index.ejs -->
<% include ./partials/top %> <%- include('./partials/top') %>
<body class="container"> <body class="container">
<% include ./partials/header %> <%- include('./partials/header') %>
<main class='main'> <main class='main'>
<div class='intro'> <div class='intro'>
<p><strong>The Codex Mythica</strong> is a database of all of the cards released for the <em>Mythic Wars</em> card game. Browse through <a href='/cards/'>all of the cards</a> in the game, or search to find the card(s) you&apos;re looking for. <p>
<strong>The Codex Mythica</strong> is a database of all of the cards released
for the <em>Mythic Wars</em> card game. Browse through
<a href='/cards/'>all of the cards</a> in the game, or search to find the
card(s) you&apos;re looking for.
</p>
</div> </div>
<% include ./partials/random_card %> <%- include('./partials/random_card') %>
<% include ./partials/search_form %> <%- include('./partials/search_form') %>
</main> </main>
<% include ./partials/footer %> <%- include('./partials/footer') %>
<% include ./partials/scripts %> <%- include('./partials/scripts') %>
</body> </body>
</html> </html>

View File

@ -4,7 +4,7 @@
<% <%
cards.forEach(card => { cards.forEach(card => {
%> %>
<% include ./preview %> <%- include('./preview', { card }) %>
<% <%
}) })
%> %>

View File

@ -2,12 +2,12 @@
<footer id="footer" class="footer" role="contentinfo"> <footer id="footer" class="footer" role="contentinfo">
<div class="footer-inner clearfix"> <div class="footer-inner clearfix">
<p> <p>
<strong>The Codex Mythica</strong> &copy; 2017-2018 <strong>The Codex Mythica</strong> &copy; 2017-2024
<a href="https://itsericwoodward.com/" class="p-author h-card" rel="author" title="Eric Woodward">Eric Woodward</a>. <em>Mythic Wars</em> and the Mythic Wars logo &copy; and &trade; Eric Woodward, licensed by Excalibre Games. <em>Excalibre Games</em> and the Excalibre Games parthenon &copy; and &trade; <a href="http://excalibregames.com/" title="Excalibre Games">Excalibre Games</a>. <a href="https://itsericwoodward.com/" class="p-author h-card" rel="author" title="Eric Woodward">Eric Woodward</a>. <em>Mythic Wars</em> and the Mythic Wars logo &copy; and &trade; Eric Woodward, licensed by Excalibre Games. <em>Excalibre Games</em> and the Excalibre Games parthenon &copy; and &trade; <a href="http://excalibregames.com/" title="Excalibre Games">Excalibre Games</a>.
</p> </p>
<p> <p>
Question or concerns? Find us on Twitter <a href="https://twitter.com/MythicWarsGame">@MythicWarsGame</a>, or send us an e-mail at Question or concerns? Send us an e-mail at
<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58; <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;
&#99;&#111;&#110;&#116;&#97;&#99;&#116;&#64;&#109;&#121;&#116;&#104;&#105;&#99;&#119;&#97;&#114;&#115;&#103;&#97;&#109;&#101;&#46;&#99;&#111;&#109;"> &#99;&#111;&#110;&#116;&#97;&#99;&#116;&#64;&#109;&#121;&#116;&#104;&#105;&#99;&#119;&#97;&#114;&#115;&#103;&#97;&#109;&#101;&#46;&#99;&#111;&#109;">
&#99;&#111;&#110;&#116;&#97;&#99;&#116;&#64;&#109;&#121;&#116;&#104;&#105;&#99;&#119;&#97;&#114;&#115;&#103;&#97;&#109;&#101;&#46;&#99;&#111;&#109; &#99;&#111;&#110;&#116;&#97;&#99;&#116;&#64;&#109;&#121;&#116;&#104;&#105;&#99;&#119;&#97;&#114;&#115;&#103;&#97;&#109;&#101;&#46;&#99;&#111;&#109;
@ -18,7 +18,7 @@
Powered by Powered by
<a href="https://nodejs.org/">Node</a>, <a href="https://nodejs.org/">Node</a>,
<a href="https://nginx.org/">nginx</a>, <a href="https://nginx.org/">nginx</a>,
<a href="https://atom.io/">Atom</a>, <a href="https://vscodium.com/">VSCodium</a>,
and <strong>the will of the gods</strong>. and <strong>the will of the gods</strong>.
</p> </p>
<a href="#" class="footer-topLink topLink">[ Go to Top ]</a> <a href="#" class="footer-topLink topLink">[ Go to Top ]</a>

View File

@ -46,7 +46,7 @@
<input type='checkbox' name='pantheons' value='aztec' <input type='checkbox' name='pantheons' value='aztec'
<%- query && ((query.pantheons && query.pantheons.indexOf('aztec') > -1) || !query.pantheons || JSON.stringify(query.pantheons) === '[]') ? "checked='checked'" : '' %> <%- query && ((query.pantheons && query.pantheons.indexOf('aztec') > -1) || !query.pantheons || JSON.stringify(query.pantheons) === '[]') ? "checked='checked'" : '' %>
/>&nbsp;<img />&nbsp;<img
class="searchForm-pantheon" src="/images/pantheons/aztec.png" alt="Aztec" /> class="searchForm-pantheon" src="/images/pantheons/aztec.png" alt="Aztec Pantheon Symbol" title="Aztec Pantheon" />
</label> </label>
</li> </li>
<li> <li>
@ -54,7 +54,7 @@
<input type='checkbox' name='pantheons' value='egyptian' <input type='checkbox' name='pantheons' value='egyptian'
<%- query && ((query.pantheons && query.pantheons.indexOf('egyptian') > -1) || !query.pantheons || JSON.stringify(query.pantheons) === '[]') ? "checked='checked'" : '' %> <%- query && ((query.pantheons && query.pantheons.indexOf('egyptian') > -1) || !query.pantheons || JSON.stringify(query.pantheons) === '[]') ? "checked='checked'" : '' %>
/>&nbsp;<img />&nbsp;<img
class="searchForm-pantheon" src="/images/pantheons/egyptian.png" alt="Egyptian" /> class="searchForm-pantheon" src="/images/pantheons/egyptian.png" alt="Egyptian Pantheon Symbol" title="Egyptian Pantheon" />
</label> </label>
</li> </li>
<li> <li>
@ -62,7 +62,7 @@
<input type='checkbox' name='pantheons' value='eternal' <input type='checkbox' name='pantheons' value='eternal'
<%- query && ((query.pantheons && query.pantheons.indexOf('eternal') > -1) || !query.pantheons || JSON.stringify(query.pantheons) === '[]') ? "checked='checked'" : '' %> <%- query && ((query.pantheons && query.pantheons.indexOf('eternal') > -1) || !query.pantheons || JSON.stringify(query.pantheons) === '[]') ? "checked='checked'" : '' %>
/>&nbsp;<img />&nbsp;<img
class="searchForm-pantheon" src="/images/pantheons/eternal.png" alt="Eternal" /> class="searchForm-pantheon" src="/images/pantheons/eternal.png" alt="Eternal Pantheon Symbol" title="Eternal Pantheon" />
</label> </label>
</li> </li>
<li> <li>
@ -70,7 +70,7 @@
<input type='checkbox' name='pantheons' value='greek' <input type='checkbox' name='pantheons' value='greek'
<%- query && ((query.pantheons && query.pantheons.indexOf('greek') > -1) || !query.pantheons || JSON.stringify(query.pantheons) === '[]') ? "checked='checked'" : '' %> <%- query && ((query.pantheons && query.pantheons.indexOf('greek') > -1) || !query.pantheons || JSON.stringify(query.pantheons) === '[]') ? "checked='checked'" : '' %>
/>&nbsp;<img />&nbsp;<img
class="searchForm-pantheon" src="/images/pantheons/greek.png" alt="Greek" /> class="searchForm-pantheon" src="/images/pantheons/greek.png" alt="Greek Pantheon Symbol" title="Greek Pantheon" />
</label> </label>
</li> </li>
<li> <li>
@ -78,7 +78,7 @@
<input type='checkbox' name='pantheons' value='japanese' <input type='checkbox' name='pantheons' value='japanese'
<%- query && ((query.pantheons && query.pantheons.indexOf('japanese') > -1) || !query.pantheons || JSON.stringify(query.pantheons) === '[]') ? "checked='checked'" : '' %> <%- query && ((query.pantheons && query.pantheons.indexOf('japanese') > -1) || !query.pantheons || JSON.stringify(query.pantheons) === '[]') ? "checked='checked'" : '' %>
/>&nbsp;<img />&nbsp;<img
class="searchForm-pantheon" src="/images/pantheons/japanese.png" alt="Japanese" /> class="searchForm-pantheon" src="/images/pantheons/japanese.png" alt="Japanese Pantheon Symbol" title="Japanese Pantheon" />
</label> </label>
</li> </li>
<li> <li>
@ -86,7 +86,7 @@
<input type='checkbox' name='pantheons' value='norse' <input type='checkbox' name='pantheons' value='norse'
<%- query && ((query.pantheons && query.pantheons.indexOf('norse') > -1) || !query.pantheons || JSON.stringify(query.pantheons) === '[]') ? "checked='checked'" : '' %> <%- query && ((query.pantheons && query.pantheons.indexOf('norse') > -1) || !query.pantheons || JSON.stringify(query.pantheons) === '[]') ? "checked='checked'" : '' %>
/>&nbsp;<img />&nbsp;<img
class="searchForm-pantheon" src="/images/pantheons/norse.png" alt="Norse" /> class="searchForm-pantheon" src="/images/pantheons/norse.png" alt="Norse Pantheon Symbol" title="Norse Pantheon" />
</label> </label>
</li> </li>
<li> <li>
@ -94,7 +94,7 @@
<input type='checkbox' name='pantheons' value='old-ones' <input type='checkbox' name='pantheons' value='old-ones'
<%- query && ((query.pantheons && query.pantheons.indexOf('old-ones') > -1) || !query.pantheons || JSON.stringify(query.pantheons) === '[]') ? "checked='checked'" : '' %> <%- query && ((query.pantheons && query.pantheons.indexOf('old-ones') > -1) || !query.pantheons || JSON.stringify(query.pantheons) === '[]') ? "checked='checked'" : '' %>
/>&nbsp;<img />&nbsp;<img
class="searchForm-pantheon" src="/images/pantheons/old-ones.png" alt="Old Ones" /> class="searchForm-pantheon" src="/images/pantheons/old-ones.png" alt="Old Ones Pantheon Symbol" title="Old Ones Pantheon" />
</label> </label>
</li> </li>
<li> <li>
@ -102,7 +102,7 @@
<input type='checkbox' name='pantheons' value='sumerian' <input type='checkbox' name='pantheons' value='sumerian'
<%- query && ((query.pantheons && query.pantheons.indexOf('sumerian') > -1) || !query.pantheons || JSON.stringify(query.pantheons) === '[]') ? "checked='checked'" : '' %> <%- query && ((query.pantheons && query.pantheons.indexOf('sumerian') > -1) || !query.pantheons || JSON.stringify(query.pantheons) === '[]') ? "checked='checked'" : '' %>
/>&nbsp;<img />&nbsp;<img
class="searchForm-pantheon" src="/images/pantheons/sumerian.png" alt="Sumerian" /> class="searchForm-pantheon" src="/images/pantheons/sumerian.png" alt="Sumerian Pantheon Symbol" title="Sumerian Pantheon" />
</label> </label>
</li> </li>
</ul> </ul>
@ -115,7 +115,7 @@
<input type='checkbox' name='elements' value='water' <input type='checkbox' name='elements' value='water'
<%- query && ((query.elements && query.elements.indexOf('water') > -1) || !query.elements || JSON.stringify(query.elements) === '[]') ? "checked='checked'" : '' %> <%- query && ((query.elements && query.elements.indexOf('water') > -1) || !query.elements || JSON.stringify(query.elements) === '[]') ? "checked='checked'" : '' %>
/>&nbsp;<img />&nbsp;<img
class="searchForm-element" src="/images/elements/water.png" alt="Water" /> class="searchForm-element" src="/images/elements/water.png" alt="Water Element Symbol" title="Water Element" />
</label> </label>
</li> </li>
<li> <li>
@ -123,7 +123,7 @@
<input type='checkbox' name='elements' value='fire' <input type='checkbox' name='elements' value='fire'
<%- query && ((query.elements && query.elements.indexOf('fire') > -1) || !query.elements || JSON.stringify(query.elements) === '[]') ? "checked='checked'" : '' %> <%- query && ((query.elements && query.elements.indexOf('fire') > -1) || !query.elements || JSON.stringify(query.elements) === '[]') ? "checked='checked'" : '' %>
/>&nbsp;<img />&nbsp;<img
class="searchForm-element" src="/images/elements/fire.png" alt="Fire" /> class="searchForm-element" src="/images/elements/fire.png" alt="Fire Element Symbol" title="Fire Element" />
</label> </label>
</li> </li>
<li> <li>
@ -131,7 +131,7 @@
<input type='checkbox' name='elements' value='earth' <input type='checkbox' name='elements' value='earth'
<%- query && ((query.elements && query.elements.indexOf('earth') > -1) || !query.elements || JSON.stringify(query.elements) === '[]') ? "checked='checked'" : '' %> <%- query && ((query.elements && query.elements.indexOf('earth') > -1) || !query.elements || JSON.stringify(query.elements) === '[]') ? "checked='checked'" : '' %>
/>&nbsp;<img />&nbsp;<img
class="searchForm-element" src="/images/elements/earth.png" alt="Earth" /> class="searchForm-element" src="/images/elements/earth.png" alt="Earth Element Symbol" title="Earth Element" />
</label> </label>
</li> </li>
<li> <li>
@ -139,7 +139,7 @@
<input type='checkbox' name='elements' value='air' <input type='checkbox' name='elements' value='air'
<%- query && ((query.elements && query.elements.indexOf('air') > -1) || !query.elements || JSON.stringify(query.elements) === '[]') ? "checked='checked'" : '' %> <%- query && ((query.elements && query.elements.indexOf('air') > -1) || !query.elements || JSON.stringify(query.elements) === '[]') ? "checked='checked'" : '' %>
/>&nbsp;<img />&nbsp;<img
class="searchForm-element" src="/images/elements/air.png" alt="Air" /> class="searchForm-element" src="/images/elements/air.png" alt="Air Element Symbol" title="Air Element" />
</label> </label>
</li> </li>
<li> <li>
@ -147,7 +147,7 @@
<input type='checkbox' name='elements' value='law' <input type='checkbox' name='elements' value='law'
<%- query && ((query.elements && query.elements.indexOf('law') > -1) || !query.elements || JSON.stringify(query.elements) === '[]') ? "checked='checked'" : '' %> <%- query && ((query.elements && query.elements.indexOf('law') > -1) || !query.elements || JSON.stringify(query.elements) === '[]') ? "checked='checked'" : '' %>
/>&nbsp;<img />&nbsp;<img
class="searchForm-element" src="/images/elements/law.png" alt="Law" /> class="searchForm-element" src="/images/elements/law.png" alt="Law Element Symbol" title="Law Element" />
</label> </label>
</li> </li>
<li> <li>
@ -155,11 +155,12 @@
<input type='checkbox' name='elements' value='chaos' <input type='checkbox' name='elements' value='chaos'
<%- query && ((query.elements && query.elements.indexOf('chaos') > -1) || !query.elements || JSON.stringify(query.elements) === '[]') ? "checked='checked'" : '' %> <%- query && ((query.elements && query.elements.indexOf('chaos') > -1) || !query.elements || JSON.stringify(query.elements) === '[]') ? "checked='checked'" : '' %>
/>&nbsp;<img />&nbsp;<img
class="searchForm-element" src="/images/elements/chaos.png" alt="Chaos" /> class="searchForm-element" src="/images/elements/chaos.png" alt="Chaos Element Symbol" title="Chaos Element" />
</label> </label>
</li> </li>
</ul> </ul>
</li> </li>
<li> <li>
<label for='races' class='js-checkToggle'>Races</label> <label for='races' class='js-checkToggle'>Races</label>
<ul> <ul>
@ -300,7 +301,7 @@
</li> </li>
<li> <li>
<label> <label>
<input type='radio' name='sort_order' value='asc' <input type='radio' name='sort_order' value='desc'
<%- query && (query.sort_order && query.sort_order === 'desc') ? "checked='checked'" : '' %> <%- query && (query.sort_order && query.sort_order === 'desc') ? "checked='checked'" : '' %>
/>&nbsp;Descending />&nbsp;Descending
</label> </label>

View File

@ -1,21 +1,21 @@
<!-- views/pages/search.ejs --> <!-- views/pages/search.ejs -->
<% include ./partials/top %> <%- include('./partials/top') %>
<body class="container"> <body class="container">
<% include ./partials/header %> <%- include('./partials/header') %>
<main class='main'> <main class='main'>
<% include ./partials/cards %> <%- include('./partials/cards') %>
<% include ./partials/search_form %> <%- include('./partials/search_form') %>
</main> </main>
<% include ./partials/footer %> <%- include('./partials/footer') %>
<% include ./partials/scripts %> <%- include('./partials/scripts') %>
</body> </body>
</html> </html>

View File

@ -1,19 +1,19 @@
<!-- views/single.ejs --> <!-- views/single.ejs -->
<% include ./partials/top %> <%- include('./partials/top') %>
<body class="container"> <body class="container">
<% include ./partials/header %> <%- include('./partials/header') %>
<main> <main>
<% include ./partials/card %> <%- include('./partials/card') %>
</main> </main>
<% include ./partials/footer %> <%- include('./partials/footer') %>
<% include ./partials/scripts %> <%- include('./partials/scripts') %>
</body> </body>
</html> </html>