portal update tribes subpage to match type subpages

This commit is contained in:
Daniel 2020-10-20 16:22:59 -04:00
parent 8ef4ea9d94
commit 4709045b4e
34 changed files with 640 additions and 2653 deletions

1
build/150.js Normal file

File diff suppressed because one or more lines are too long

1
build/171.js Normal file

File diff suppressed because one or more lines are too long

1
build/181.css Normal file

File diff suppressed because one or more lines are too long

1
build/181.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[4],{1069:function(e,t,n){},1072:function(e,t,n){"use strict";n.r(t),n.d(t,"default",(function(){return g}));var a=n(169),r=n.n(a),o=n(82),l=n.n(o),c=n(63),i=n.n(c),s=n(167),u=n.n(s),f=n(168),m=n.n(f),d=n(131),h=n.n(d),p=n(0),b=n.n(p),v=n(83),E=n(57);n(1069),n(3);function y(e){var t=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}();return function(){var n,a=h()(e);if(t){var r=h()(this).constructor;n=Reflect.construct(a,arguments,r)}else n=a.apply(this,arguments);return m()(this,n)}}var k=function(){return b.a.createElement("a",{href:"https://github.com/chaoticbackup",className:"name",rel:"noreferrer noopener",target:"_blank"},"Chaotic Backup Project")},w=function(e){var t=e.block,n=e.text,a=e.sets;return b.a.createElement("div",{className:"lore"},b.a.createElement("div",{className:"block"},t),n.map((function(e,t){return b.a.createElement("div",{key:t,dangerouslySetInnerHTML:{__html:e}})})),a.map((function(e,t){if(e.text&&e.text.length>0)return b.a.createElement("div",{className:"set",key:t},b.a.createElement("div",{className:"title"},e.title),e.text.map((function(e,t){return b.a.createElement("div",{key:t},e)})))})))},g=function(e){u()(n,e);var t=y(n);function n(){var e;l()(this,n);for(var a=arguments.length,r=new Array(a),o=0;o<a;o++)r[o]=arguments[o];return(e=t.call.apply(t,[this].concat(r))).state={lore:[]},e}return i()(n,[{key:"componentDidMount",value:function(){var e=this;fetch("/src/json/starter_lore.json").then((function(e){return e.json()})).then((function(t){e.setState({lore:t})})).catch((function(){e.setState({lore:[{block:"Unable to load lore...",text:[]}]})}))}},{key:"render",value:function(){return b.a.createElement("div",null,b.a.createElement("br",null),b.a.createElement("div",{className:"with-love"},b.a.createElement("div",null,"Welcome to the ",b.a.createElement(k,null),"."),b.a.createElement("span",null,"Built by fans for fans."),b.a.createElement("br",null),b.a.createElement("br",null),b.a.createElement("div",null,"Made with ",b.a.createElement("span",{className:"heart"},"♥")," by",b.a.createElement("br",null),"Danude Sandstorm (Project Lead)",b.a.createElement("br",null),"Chiodosin1 (Database Contributions)",b.a.createElement("br",null),"Afjak and Blitser (Art and Knowledge)"),b.a.createElement("div",null,"Do you like the site? You can donate to support it!"),b.a.createElement("div",{className:"donate"},b.a.createElement(E.e,null)),b.a.createElement("div",{className:"lore"},"We were unsatisfied with the options on how to search for cards. I took the design of the old Chaotic website and added my own modernizations. With an extensive lists of search options in the ",b.a.createElement(v.b,{to:"/collection"},"collection"),", you'll find deck building mores streamlined than ever before. Chaotic is full of rich lore, but unfortunately the best database of official lore disapeared when the ",b.a.createElement(v.b,{to:"/portal"},"Portal to Perim")," disapeared along with the site. You can again explore the official lore and information of Creatures!"),b.a.createElement("br",null),this.state.lore.length>0?this.state.lore.map((function(e,t){return b.a.createElement(w,r()({key:t},e))})):"Loading lore entries..."))}}]),n}(b.a.Component)}}]);

View File

@ -1 +0,0 @@
.icon14{height:14px;padding-bottom:2px}.icon16{height:16px}.icon20{height:20px}.icon24{height:24px}.bigger{font-size:14px}.name{-webkit-user-select:all;-moz-user-select:all;-ms-user-select:all;user-select:all}.name .subname:before{content:"\a ";white-space:pre}.name .subname{font-size:13px;padding-bottom:4px;display:inherit}.portal .navbar h1{font-size:16px}.portal .navbar ul{list-style-type:none;margin:0;padding:0;overflow:hidden;background-color:#333}.portal .navbar li{float:left}.portal .navbar .dropbtn,.portal .navbar li a{display:inline-block;color:#fff;text-align:center;padding:14px 16px;text-decoration:none}.portal .navbar .dropdown:hover .dropbtn,.portal .navbar li a:hover{background-color:red}.portal .navbar li.dropdown{display:inline-block}.portal .navbar .dropdown-content{display:none;position:absolute;background-color:#333;min-width:140px;box-shadow:0 8px 16px 0 rgba(0,0,0,.2);z-index:1}.portal .navbar .dropdown-content a{color:#fff;padding:12px 16px;text-decoration:none;display:block;text-align:left}.portal .navbar .dropdown:hover .dropdown-content{display:block}.portal .magnifying-glass{cursor:pointer;transition:color .2s;z-index:1;vertical-align:middle;fill:currentColor;height:18px;min-width:18px;width:18px}.portal .search .results div{padding-bottom:10px}.portal .search .results a{font-size:16px;line-height:20px}.portal .entry{font-size:1.2em}.portal .entry .title{font-weight:700;font-size:16px}.portal .entry .left{float:left;width:100px}.portal .entry .right{float:right;width:86%}.portal .entry .left .title{text-align:left;padding-bottom:10px}.portal .entry .icon14,.portal .entry .icon16,.portal .entry .icon20,.portal .entry .icon24{vertical-align:middle}.portal .entry .entry_content{min-height:550px;height:calc(100vh - 300px);overflow-y:auto;width:100%;position:relative}.portal .entry .entry_content .entry_splash{padding-bottom:4px}.portal .entry .entry_content .entry_splash img{max-width:100%}.portal .entry .entry_content .entry_splash .arrow{position:absolute;color:#f1f1f1;font-size:40px;font-weight:700;width:100%;top:95%}.portal .entry .entry_content .entry_body{position:relative;max-width:100%;padding-bottom:4px;display:flex;flex-wrap:wrap}.portal .entry .entry_content .entry_body hr{margin:0}.portal .entry .entry_content .entry_body .title{min-width:100%}.portal .entry .entry_content .entry_body .title hr{margin-top:8px}.portal .entry .entry_content .entry_body .column>div,.portal .entry .entry_content .entry_body .nocolumn>div{padding:8px}.portal .entry .entry_content .entry_body .column:nth-child(2){flex-grow:1;text-align:left;min-width:0;width:30%}.portal .entry .entry_content .entry_body .column:last-child{flex-grow:2;min-width:0;flex:60%;border-left:1px solid #fff}.portal .entry .entry_content .entry_body .ability{white-space:pre-line;word-wrap:break-all}.portal .entry .entry_content .entry_body div{white-space:pre-line}.portal .entry .entry_content::-webkit-scrollbar{width:1px}.portal .entry .cat_title{text-align:left;background-color:#1a1a1a;font-weight:700;font-size:16px;padding-top:1px;padding-left:4px}.portal .entry .entry_nav{background-color:#1a1a1a;overflow-x:scroll;overflow-y:hidden;white-space:nowrap}.portal .entry .entry_nav .nav_item{display:inline-block;margin-right:3px;margin-left:3px;min-width:96px}.portal .entry .entry_nav .nav_item img{height:100px}.portal .entry.base_path .cat_title,.portal .entry.base_path .entry_nav{background-color:inherit}.portal .entry.base_path .cat_title{padding-top:1em;padding-bottom:1em}.portal .entry.base_path .entry_nav{overflow-y:auto;display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-start;align-content:space-between;position:relative}.portal .entry.base_path .entry_nav .nav_item{margin:3px;max-width:106px;white-space:normal;overflow-wrap:break-word;display:flex;justify-content:flex-end;flex-direction:column}.portal .entry .modal{position:fixed;z-index:10;padding-top:50px;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:#000;background-color:rgba(0,0,0,.9)}.portal .entry .modal.hidden{display:none}.portal .entry .modal-content{margin:auto;display:block;max-height:calc(100vh - 100px);max-width:90vw}.portal .entry .caption{margin:auto;display:block;width:80%;max-width:700px;text-align:center;color:#ccc;padding:10px 0;height:150px}.portal .entry #caption,.portal .entry .modal-content{-webkit-animation-name:zoom;-webkit-animation-duration:.6s;animation-name:zoom;animation-duration:.6s}@-webkit-keyframes zoom{0%{-webkit-transform:scale(0)}to{-webkit-transform:scale(1)}}@keyframes zoom{0%{transform:scale(0)}to{transform:scale(1)}}.portal .entry .close{position:fixed;top:35px;right:35px;color:#f1f1f1;font-size:40px;font-weight:700;transition:.3s}.portal .entry .close:focus,.portal .entry .close:hover{color:#bbb;text-decoration:none;cursor:pointer}

File diff suppressed because one or more lines are too long

1
build/767.js Normal file
View File

@ -0,0 +1 @@
(self.webpackChunkchaoticbackup=self.webpackChunkchaoticbackup||[]).push([[767],{8640:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>g});var r=n(7154),a=n.n(r),l=n(4575),o=n.n(l),c=n(3913),i=n.n(c),s=n(2205),u=n.n(s),f=n(8585),m=n.n(f),h=n(9754),d=n.n(h),p=n(7294),b=n(3727),v=n(2195);n(2188);function E(e){var t=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}();return function(){var n,r=d()(e);if(t){var a=d()(this).constructor;n=Reflect.construct(r,arguments,a)}else n=r.apply(this,arguments);return m()(this,n)}}var k=function(){return p.createElement("a",{href:"https://github.com/chaoticbackup",className:"name",rel:"noreferrer noopener",target:"_blank"},"Chaotic Backup Project")},y=function(e){var t=e.block,n=e.text,r=e.sets;return p.createElement("div",{className:"lore"},p.createElement("div",{className:"block"},t),n.map((function(e,t){return p.createElement("div",{key:t,dangerouslySetInnerHTML:{__html:e}})})),r.map((function(e,t){if(e.text&&e.text.length>0)return p.createElement("div",{className:"set",key:t},p.createElement("div",{className:"title"},e.title),e.text.map((function(e,t){return p.createElement("div",{key:t},e)})))})))},g=function(e){u()(n,e);var t=E(n);function n(){var e;o()(this,n);for(var r=arguments.length,a=new Array(r),l=0;l<r;l++)a[l]=arguments[l];return(e=t.call.apply(t,[this].concat(a))).state={lore:[]},e}return i()(n,[{key:"componentDidMount",value:function(){var e=this;fetch("/public/json/starter_lore.json").then((function(e){return e.json()})).then((function(t){e.setState({lore:t})})).catch((function(){e.setState({lore:[{block:"Unable to load lore...",text:[]}]})}))}},{key:"render",value:function(){return p.createElement("div",null,p.createElement("br",null),p.createElement("div",{className:"with-love"},p.createElement("div",null,"Welcome to the ",p.createElement(k,null),"."),p.createElement("span",null,"Built by fans for fans."),p.createElement("br",null),p.createElement("br",null),p.createElement("div",null,"Made with ",p.createElement("span",{className:"heart"},"♥")," by",p.createElement("br",null),"Danude Sandstorm (Project Lead)",p.createElement("br",null),"Chiodosin1 (Database Contributions)",p.createElement("br",null),"Afjak and Blitser (Art and Knowledge)"),p.createElement("div",null,"Do you like the site? You can donate to support it!"),p.createElement("div",{className:"donate"},p.createElement(v.U9,null)),p.createElement("div",{className:"lore"},"We were unsatisfied with the options on how to search for cards. I took the design of the old Chaotic website and added my own modernizations. With an extensive lists of search options in the ",p.createElement(b.rU,{to:"/collection"},"collection"),", you'll find deck building mores streamlined than ever before. Chaotic is full of rich lore, but unfortunately the best database of official lore disapeared when the ",p.createElement(b.rU,{to:"/portal"},"Portal to Perim")," disapeared along with the official site. You can again explore the official lore and information!"),p.createElement("br",null),this.state.lore.length>0?this.state.lore.map((function(e,t){return p.createElement(y,a()({key:t},e))})):"Loading lore entries..."))}}]),n}(p.Component)}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -11,6 +11,21 @@ object-assign
* MIT Licensed
*/
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
@ -42,15 +57,6 @@ and limitations under the License.
* LICENSE file in the root directory of this source tree.
*/
/** @license React v16.13.1
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v16.13.1
* react-is.production.min.js
*
@ -60,7 +66,16 @@ and limitations under the License.
* LICENSE file in the root directory of this source tree.
*/
/** @license React v16.13.1
/** @license React v16.14.0
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v16.14.0
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.

2402
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
"description": "Chaotic Backup",
"scripts": {
"start": "webpack-cli serve --mode development --env development",
"build": "webpack -p",
"build": "webpack",
"lint": "tsc --noEmit && eslint '*/**/*.{js,ts,tsx}'",
"lint:fix": "tsc --noEmit && eslint '*/**/*.{js,ts,tsx}' --quiet --fix",
"test": "cross-env TS_NODE_COMPILER_OPTIONS='{ \"module\": \"commonjs\" }' mocha -r ts-node/register -r ignore-styles -r jsdom-global/register src/**/*.spec.ts"
@ -16,7 +16,7 @@
"author": "Danude Sandstorm",
"license": "MIT",
"dependencies": {
"@loadable/component": "^5.13.2",
"@loadable/component": "^5.14.0",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
"@material-ui/styles": "^4.10.0",
@ -40,7 +40,7 @@
},
"devDependencies": {
"@babel/cli": "^7.12.1",
"@babel/core": "^7.12.1",
"@babel/core": "^7.12.3",
"@babel/node": "^7.12.1",
"@babel/plugin-proposal-class-properties": "^7.12.1",
"@babel/plugin-proposal-decorators": "^7.12.1",
@ -57,7 +57,7 @@
"@babel/runtime": "^7.12.1",
"@types/chai": "^4.2.14",
"@types/mocha": "^8.0.3",
"@types/react": "^16.9.52",
"@types/react": "^16.9.53",
"@types/react-dom": "^16.9.8",
"@types/react-router-dom": "^5.1.6",
"@typescript-eslint/eslint-plugin": "^3.3.0",
@ -72,22 +72,22 @@
"eslint-plugin-babel": "^5.3.1",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-react": "^7.21.4",
"eslint-plugin-react": "^7.21.5",
"eslint-plugin-react-hooks": "^4.1.2",
"ignore-styles": "^5.0.1",
"jsdom": "^16.4.0",
"jsdom-global": "^3.0.2",
"mini-css-extract-plugin": "^1.0.0",
"mocha": "^8.1.3",
"mini-css-extract-plugin": "^1.1.1",
"mocha": "^8.2.0",
"node-sass": "^4.14.1",
"postcss": "^8.1.0",
"postcss": "^8.1.2",
"sass-loader": "^10.0.3",
"style-loader": "^2.0.0",
"terser-webpack-plugin": "^5.0.0",
"ts-node": "^9.0.0",
"typescript": "^4.0.3",
"webpack": "^5.1.3",
"webpack-cli": "^4.0.0",
"webpack-cli": "^4.1.0",
"webpack-dev-server": "^3.11.0"
},
"browser": {

View File

@ -4,16 +4,16 @@ export function Initiative(props) {
const { initiative } = props;
let image = null;
if (["Danian", "Generic", "Mipedian", "OverWorld", "UnderWorld", "M'arrillian"].indexOf(initiative) > -1) {
image = <img className="icon16" style={{ verticalAlign: 'middle' }} src={("/src/img/icons/tribes/" + initiative + ".png").toLowerCase()} />;
image = <img className="icon16" style={{ verticalAlign: 'middle' }} src={("/public/img/icons/tribes/" + initiative + ".png").toLowerCase()} />;
}
else if (["courage", "power", "speed", "wisdom"].indexOf(initiative.toLowerCase()) > -1) {
image = <img className="icon16" style={{ verticalAlign: 'middle' }} src={("/src/img/icons/disciplines/" + initiative + ".png").toLowerCase()} />;
image = <img className="icon16" style={{ verticalAlign: 'middle' }} src={("/public/img/icons/disciplines/" + initiative + ".png").toLowerCase()} />;
}
else if (["fire", "air", "earth", "water"].indexOf(initiative.toLowerCase()) > -1) {
image = <img className="icon16" style={{ verticalAlign: 'middle' }} src={("/src/img/icons/elements/" + initiative + ".png").toLowerCase()} />;
image = <img className="icon16" style={{ verticalAlign: 'middle' }} src={("/public/img/icons/elements/" + initiative + ".png").toLowerCase()} />;
}
else if (initiative.toLowerCase() == "mugic counter") {
image = <img className="icon16" style={{ verticalAlign: 'middle' }} src={("/src/img/icons/mugic/generic.png").toLowerCase()} />;
image = <img className="icon16" style={{ verticalAlign: 'middle' }} src={("/public/img/icons/mugic/generic.png").toLowerCase()} />;
}
return (<span>{!props.notitle && ("Initiative: ")}{image}&nbsp;{initiative}</span>);
}

View File

@ -3,22 +3,22 @@ import API from '../SpreadsheetData';
export function AttackIcon(props) {
const attack = "attack" + ((props.bp && props.bp >= 0) ? "_" + props.bp : "");
return <img className={props.size || "icon16"} src={`/src/img/icons/attack/${attack}.png`} />;
return <img className={props.size || "icon16"} src={`/public/img/icons/attack/${attack}.png`} />;
}
export function BattlegearIcon(props) {
return <img className={props.size || "icon16"} src="/src/img/icons/battlegear.png" />;
return <img className={props.size || "icon16"} src="/public/img/icons/battlegear.png" />;
}
export function LocationIcon(props) {
return <img className={props.size || "icon16"} src="/src/img/icons/location.png" />;
return <img className={props.size || "icon16"} src="/public/img/icons/location.png" />;
}
export function Rarity(props) {
const { set, rarity } = props;
return (
<span>
{set !== 'PE1' && <img className={props.size || "icon16"} style={{ verticalAlign: 'middle' }} src={("/src/img/icons/set/" + set + "/" + rarity + ".png").toLowerCase()} />}
{set !== 'PE1' && <img className={props.size || "icon16"} style={{ verticalAlign: 'middle' }} src={("/public/img/icons/set/" + set + "/" + rarity + ".png").toLowerCase()} />}
{!props.notext && <>{API.sets[props.set]}&nbsp;|&nbsp;{props.rarity}</>}
</span>
);

View File

@ -15,23 +15,23 @@ export function Name(props) {
export function Mugic(props) {
const type = (props.tribe || "generic") + (props.amount != undefined ? `_${props.amount}` : "");
const src = ("/src/img/icons/mugic/" + type + ".png").toLowerCase();
const src = ("/public/img/icons/mugic/" + type + ".png").toLowerCase();
return <img className={props.size || "icon20"} src={src} alt={"MC"} />;
}
export function Element(props) {
if (props.value) {
return <img className={props.size || "icon20"} src={("/src/img/icons/elements/" + props.element + ".png").toLowerCase()} />;
return <img className={props.size || "icon20"} src={("/public/img/icons/elements/" + props.element + ".png").toLowerCase()} />;
}
else {
return <img className={props.size || "icon20"} src={("/src/img/icons/elements/" + props.element + "-inactive.png").toLowerCase()} />;
return <img className={props.size || "icon20"} src={("/public/img/icons/elements/" + props.element + "-inactive.png").toLowerCase()} />;
}
}
export function Tribe(props) {
return <img className={props.size || "icon16"} src={("/src/img/icons/tribes/" + props.tribe + ".png").toLowerCase()} />;
return <img className={props.size || "icon16"} src={("/public/img/icons/tribes/" + props.tribe + ".png").toLowerCase()} />;
}
export function Discipline(props) {
return <img className={props.size || "icon16"} src={("/src/img/icons/disciplines/" + props.discipline + ".png").toLowerCase()} />;
return <img className={props.size || "icon16"} src={("/public/img/icons/disciplines/" + props.discipline + ".png").toLowerCase()} />;
}

View File

@ -37,7 +37,7 @@ export function Donate(props) {
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">
<input type="hidden" name="cmd" value="_s-xclick" />
<input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----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-----END PKCS7-----" />
<a href="https://www.paypal.com/cgi-bin/webscr"><input type="image" src="/src/img/btn_donate_SM.gif" border="0" name="submit" alt="PayPal Donate" /></a>
<a href="https://www.paypal.com/cgi-bin/webscr"><input type="image" src="/public/img/btn_donate_SM.gif" border="0" name="submit" alt="PayPal Donate" /></a>
{ /* <img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1" /> */}
</form>
);

View File

@ -222,18 +222,18 @@ export default class SearchCollection extends React.Component {
// });
const tribes = gen("tribes", "inline", (item) => {
return (<span><img className="icon16" src={"/src/img/icons/tribes/"+item+".png"} /></span>);
return (<span><img className="icon16" src={"/public/img/icons/tribes/"+item+".png"} /></span>);
});
const elements = gen("elements", "inline", (item) => {
return (<span><img className="icon20" src={"/src/img/icons/elements/"+item+".png"} />&nbsp;</span>);
return (<span><img className="icon20" src={"/public/img/icons/elements/"+item+".png"} />&nbsp;</span>);
}).slice(0, -2);
const disciplines = [];
Object.keys(this.input.disciplines).forEach((item, i) => {
if (i == 4) return;
disciplines.push(<label key={i} className="disciplines"><input type="text" name={item} value={this.input.disciplines[item]} onChange={e => this.handleChange(e, "disciplines")} />
<img className="icon20" style={{ verticalAlign: 'middle', padding: "0px 2px" }} src={"/src/img/icons/disciplines/"+item+".png"} />
<img className="icon20" style={{ verticalAlign: 'middle', padding: "0px 2px" }} src={"/public/img/icons/disciplines/"+item+".png"} />
</label>);
});

View File

@ -0,0 +1,81 @@
export const Tribes = ['Danian', 'Mipedian', "M'arrillian", 'OverWorld', 'UnderWorld', 'Frozen'] as const;
export const CreatureTribes = ['Danian', 'Mipedian', "M'arrillian", 'OverWorld', 'UnderWorld', 'Frozen', 'Tribeless'] as const;
export const MugicTribes = ['Danian', 'Mipedian', "M'arrillian", 'OverWorld', 'UnderWorld', 'Frozen', 'Generic'] as const;
export type Tribe = typeof Tribes[number];
export type CreatureTribe = typeof CreatureTribes[number];
export type MugicTribe = typeof MugicTribes[number];
export const CardTypes = ['Attacks', 'Battlegear', 'Creatures', 'Locations', 'Mugic'] as const;
export type CardType = typeof CardTypes[number];
export function parseTribe(input: string): CreatureTribe | MugicTribe | undefined;
export function parseTribe(input: string, type: 'Mixed'): Tribe | 'Mixed' | undefined;
export function parseTribe(input: string, type: 'Mugic'): MugicTribe | undefined;
export function parseTribe(input: string, type: 'Creatures'): CreatureTribe | undefined;
export function parseTribe(input: string, type: 'Mugic' | 'Creatures'): CreatureTribe | MugicTribe | undefined;
export function parseTribe(
input: string, type?: 'Mugic' | 'Creatures' | 'Mixed'
): CreatureTribe | MugicTribe | 'Mixed' | undefined {
switch (input.toLowerCase()) {
case 'danian':
case 'danians':
return 'Danian';
case 'marrillian':
case 'marrillians':
case 'm\'arrillian':
case 'm\'arrillians':
return "M'arrillian";
case 'mipedian':
case 'mipedians':
return 'Mipedian';
case 'overworld':
case 'overworlders':
return 'OverWorld';
case 'underworld':
case 'underworlders':
return 'UnderWorld';
case 'mixed':
return 'Mixed';
case 'tribeless':
if (type === 'Mixed') return 'Mixed';
if (type === 'Mugic') return 'Generic';
return 'Tribeless';
case 'generic':
if (type === 'Mixed') return 'Mixed';
if (type === 'Creatures') return 'Tribeless';
return 'Generic';
}
}
export function generify(tribe: CreatureTribe | MugicTribe, type: 'Mugic'): MugicTribe;
export function generify(tribe: CreatureTribe | MugicTribe, type: 'Creatures'): CreatureTribe;
export function generify(tribe: CreatureTribe | MugicTribe, type: 'Mugic' | 'Creatures'): MugicTribe | CreatureTribe;
export function generify(tribe: CreatureTribe | MugicTribe, type: 'Mugic' | 'Creatures') {
if (type === 'Creatures') {
if (tribe === 'Generic') tribe = 'Tribeless';
return tribe;
}
else if (type === 'Mugic') {
if (tribe === 'Tribeless') tribe = 'Generic';
return tribe;
}
}
export function parseType(input: string): CardType | undefined {
switch (input.toLowerCase()) {
case 'attack':
case 'attacks':
return 'Attacks';
case 'battlegear':
return 'Battlegear';
case 'creature':
case 'creatures':
return 'Creatures';
case 'location':
case 'locations':
return 'Locations';
case 'mugic':
return 'Mugic';
}
}

View File

@ -0,0 +1,84 @@
import { CardType } from './card_types';
export interface BaseCard {
gsx$name: string
gsx$tags?: string
gsx$type: CardType
gsx$set: string
gsx$rarity: string
gsx$image: string
gsx$thumb: string
gsx$ability: string
gsx$flavortext: string
gsx$splash: string
gsx$types: string
gsx$unique: number | string
gsx$legendary: number | string
gsx$loyal: number | string
gsx$alt?: string
gsx$alt2?: string
gsx$ic?: string // imgur card
gsx$if?: string // imgur fullart
}
export interface Attack extends BaseCard {
gsx$fire: number | string
gsx$air: number | string
gsx$earth: number | string
gsx$water: number | string
gsx$base: number | string
gsx$bp: number | string
}
export interface Battlegear extends BaseCard {
gsx$subtype: string
}
export interface Creature extends BaseCard {
gsx$tribe: string
gsx$courage: string | number
gsx$power: string | number
gsx$wisdom: string | number
gsx$speed: string | number
gsx$energy: string | number
gsx$elements: string
gsx$brainwashed: string
gsx$mugicability: string | number
gsx$avatar?: string
gsx$subtype: string
gsx$ia?: string // imgur avatar
}
export interface Location extends BaseCard {
gsx$initiative: string
gsx$subtype: string
}
export interface Mugic extends BaseCard {
gsx$tribe: string
gsx$cost: number | string
}
export type Card = Attack | Battlegear | Creature | Location | Mugic;
export type Code = string;
export function isAttack(card: Card): card is Attack {
return (card.gsx$type === 'Attacks');
}
export function isBattlegear(card: Card): card is Battlegear {
return (card.gsx$type === 'Battlegear');
}
export function isCreature(card: Card): card is Creature {
return (card.gsx$type === 'Creatures');
}
export function isLocation(card: Card): card is Location {
return (card.gsx$type === 'Locations');
}
export function isMugic(card: Card): card is Mugic {
return (card.gsx$type === 'Mugic');
}

View File

@ -1,14 +1,14 @@
import React from 'react';
import Interactive from 'react-interactive';
import { Link, Route } from 'react-router-dom';
import { observable } from 'mobx';
import { observer, inject } from 'mobx-react';
import loki from 'lokijs';
import s from '../../styles/app.style';
import API from '../SpreadsheetData';
import { Loading } from '../Snippets';
import Creature from './Single/Creature';
import Mugic from './Single/Mugic';
import { observable } from 'mobx';
import { inject, observer } from 'mobx-react';
import React from 'react';
import { Route } from 'react-router-dom';
import { Loading } from '../../Snippets';
import API from '../../SpreadsheetData';
import Creature from '../Single/Creature';
import Mugic from '../Single/Mugic';
import { sortCardName, thumb_link } from './common';
@inject((stores, props, context) => props) @observer
export default class Tribes extends React.Component {
@ -40,10 +40,8 @@ export default class Tribes extends React.Component {
const filter = this.filter.addCollection('filter');
var pview = filter.addDynamicView('filter');
pview.applySimpleSort('gsx$name');
let temp;
temp = API.portal.creatures.find({ 'gsx$tribe': tribe });
temp.forEach((v) => { delete v.$loki });
filter.insert(temp);
@ -55,30 +53,28 @@ export default class Tribes extends React.Component {
const results = pview.data();
this.filter.removeCollection('filter');
const bottom_nav = results.map((card, i) => {
let card_data, url;
const bottom_nav = results
.sort(sortCardName)
.map((card, i) => {
let url;
if (card.gsx$type == "Mugic") {
card_data = API.cards.mugic.findOne({ 'gsx$name': card.gsx$name });
url = "/portal/" + tribe + "/Mugic/" + encodeURIComponent(card.gsx$name);
}
if (card.gsx$type == "Creatures") {
card_data = API.cards.creatures.findOne({ 'gsx$name': card.gsx$name });
else if (card.gsx$type == "Creatures") {
url = "/portal/" + tribe + "/Creatures/" + encodeURIComponent(card.gsx$name);
}
// Prevent site from crashing due to misspelled/missing data
if (!card_data) return (<div key={i}></div>);
return (<div key={i} className="nav_item">
<Interactive as={Link} {...s.link} to={url}>
<span>{card.gsx$name.split(",")[0]}</span><br />
<img className="thumb" src={API.base_image + card_data.gsx$thumb} />
</Interactive>
</div>);
return thumb_link(card, i, url);
});
const base_path = (path.length > 4) ? false : true;
if (base_path) {
return (<div className="entry tribe base_path">
<div className="cat_title">{path[2]}</div>
<div className="entry_nav">{bottom_nav}</div>
</div>);
}
return (<div className="entry tribe">
<div className="entry_content">
<Route path={`${this.props.match.url}/Creatures/:card`} component={Creature} />

View File

@ -1,11 +1,11 @@
import React from 'react';
import Interactive from 'react-interactive';
import { Link, Route } from 'react-router-dom';
import { Route } from 'react-router-dom';
import { observable } from 'mobx';
import { observer, inject } from 'mobx-react';
import s from '../../styles/app.style';
import API from '../SpreadsheetData';
import { Loading } from '../Snippets';
import API from '../../SpreadsheetData';
import { Loading } from '../../Snippets';
import { sortCardName, thumb_link } from './common';
@inject((stores, props, context) => props) @observer
export default class Category extends React.Component {
@ -30,23 +30,6 @@ export default class Category extends React.Component {
return (<Loading />);
}
const create_link = (card, i, url) => {
const data = API.cards[this.type].findOne({ 'gsx$name': card.gsx$name });
// Prevent site from crashing due to misspelled/missing data
if (!data) return (<div key={i}></div>);
return (<div key={i} className="nav_item">
<Interactive as={Link}
to={url || `/portal/${this.props.type}/${card.gsx$name}`}
{...s.link}
>
<span>{card.gsx$name.split(",")[0]}</span><br />
<img className="thumb" src={API.base_image + data.gsx$thumb}></img>
</Interactive>
</div>);
};
let base_path = true;
let cat_title = "";
let top_content = (<div />);
@ -86,16 +69,18 @@ export default class Category extends React.Component {
);
bottom_nav = ((tribe) ?
API.portal[this.type].chain().find({ 'gsx$tribe': tribe }).simplesort('gsx$name').data()
API.portal[this.type].chain().find({ 'gsx$tribe': tribe }).data()
:
API.portal[this.type].chain().simplesort('gsx$name').data()
).map((card_portal, i) => {
API.portal[this.type].chain().data()
)
.sort(sortCardName)
.map((card_portal, i) => {
const url = ((tribe) ?
`/portal/${this.props.type}/${card_portal.gsx$tribe}/${encodeURIComponent(card_portal.gsx$name)}`
:
`/portal/${this.props.type}/${encodeURIComponent(card_portal.gsx$name)}`
);
return create_link(card_portal, i, url);
return thumb_link(card_portal, i, url);
});
}
else {
@ -107,10 +92,8 @@ export default class Category extends React.Component {
cat_title = this.props.type;
bottom_nav = API.portal[this.type].data
.sort((a, b) => (a.gsx$name > b.gsx$name) ? 1 : -1)
.map((card_portal, i) => {
return create_link(card_portal, i);
});
.sort(sortCardName)
.map(thumb_link);
}
if (base_path) {

View File

@ -0,0 +1,51 @@
import React from 'react';
import Interactive from 'react-interactive';
import { Link } from 'react-router-dom';
import s from '../../../styles/app.style';
import { Card } from "../../common/definitions";
import API from '../../SpreadsheetData';
export function cleanCardName (card: Card) {
return card.gsx$name.split(",")[0].replace(/\(Unused\)/, "");
}
export function sortCardName (a: Card, b: Card) {
return (a.gsx$name.toLowerCase().replace(/\(unused\)/, "") > b.gsx$name.toLowerCase().replace(/\(unused\)/, "") ? 1 : -1);
}
export function text_link (card: Card, i: number) {
let url;
if (["Attacks", "Battlegear", "Creatures", "Locations", "Mugic"].includes(card.gsx$type)) {
url = `/portal/${card.gsx$type}/${card.gsx$name}`;
}
if (!url) return (<div key={i} style={{display: "none"}}></div>);
return (<div key={i}>
<Interactive as={Link} {...s.link} to={url}>{card.gsx$name}</Interactive>
<br />
</div>);
}
export function thumb_link (portalCard: Card, i: number, url?: string) {
let collectionCard: Card | null = null;
if (["Attacks", "Battlegear", "Creatures", "Locations", "Mugic"].includes(portalCard.gsx$type)) {
if (!url) url = `/portal/${portalCard.gsx$type}/${portalCard.gsx$name}`;
collectionCard = API.cards[portalCard.gsx$type.toLowerCase()].findOne({ 'gsx$name': portalCard.gsx$name });
}
// Prevent site from crashing due to misspelled/missing data
if (!collectionCard || !url) {
console.warn("missing: " + portalCard.gsx$name);
return (<div key={i} style={{display: "none"}} className="nav_item"></div>);
}
return (<div key={i} className="nav_item">
<Interactive as={Link} to={url} {...s.link}>
<span>{cleanCardName(collectionCard)}</span><br />
<img className="thumb" src={API.base_image + (collectionCard.gsx$thumb ? collectionCard.gsx$thumb : API.thumb_missing)}></img>
</Interactive>
</div>);
}

View File

@ -0,0 +1,50 @@
import React from 'react';
import { Link } from 'react-router-dom';
import API from '../SpreadsheetData';
import { SearchButton } from '../Snippets';
export default function Header() {
function voidClick(e) {
e.preventDefault();
e.stopPropagation();
}
const tribes = API.tribes.map((tribe, i) => {
return (
<li key={i} className="dropdown">
<Link to=" " className="dropbtn" onClick={voidClick}>{tribe}</Link>
<div className="dropdown-content">
<Link to={"/portal/"+tribe}>All</Link>
<Link to={"/portal/Creatures/"+tribe}> Creatures</Link>
<Link to={"/portal/Mugic/"+tribe}> Mugic</Link>
</div>
</li>
);
});
return (
<div className="navbar">
<ul>
<li>
<Link to="/portal/">Home</Link>
</li>
<li>
<Link to="/portal/Search"><SearchButton />Search</Link>
</li>
<li className="dropdown">
<Link to=" " onClick={voidClick} className="dropbtn">Types</Link>
<div className="dropdown-content">
<Link to="/portal/Attacks">Attacks</Link>
<Link to="/portal/Battlegear">Battlegear</Link>
<Link to="/portal/Creatures">Creatures</Link>
<Link to="/portal/Locations">Locations</Link>
<Link to="/portal/Mugic">Mugic</Link>
</div>
</li>
{tribes}
</ul>
</div>
);
}

View File

@ -1,12 +1,10 @@
import React from 'react';
import Interactive from 'react-interactive';
import { Link } from 'react-router-dom';
import API from '../SpreadsheetData';
import { observable } from "mobx";
import { observer, inject } from 'mobx-react';
import loki from 'lokijs';
import s from '../../styles/app.style';
import { SearchButton } from '../Snippets';
import { sortCardName, text_link, thumb_link } from './Category/common.tsx';
@inject((stores, props, context) => props) @observer
export default class SearchPortal extends React.Component {
@ -66,44 +64,6 @@ class DBSearch extends React.Component {
return (<div style={{ minHeight: '50px' }}></div>);
}
const text_link = (card, i) => {
let url;
if (["Attacks", "Battlegear", "Creatures", "Locations", "Mugic"].includes(card.gsx$type)) {
url = `/portal/${card.gsx$type}/${card.gsx$name}`;
}
if (!url) return (<span key={i}></span>);
return (<div key={i}>
<Interactive as={Link} {...s.link} to={url}>{card.gsx$name}</Interactive>
<br />
</div>);
};
const thumb_link = (card, i) => {
let url;
let data;
if (["Attacks", "Battlegear", "Creatures", "Locations", "Mugic"].includes(card.gsx$type)) {
url = `/portal/${card.gsx$type}/${card.gsx$name}`;
data = API.cards[card.gsx$type.toLowerCase()].findOne({ 'gsx$name': card.gsx$name });
}
// Prevent site from crashing due to misspelled/missing data
if (!data || !url) return (<span key={i}></span>);
const name = card.gsx$name.split(",")[0].replace(/\(Unused\)/, "");
return (<div key={i} className="nav_item">
<Interactive as={Link}
to={url}
{...s.link}
>
<span>{name}</span><br />
<img className="thumb" src={API.base_image + (data.gsx$thumb ? data.gsx$thumb : API.thumb_missing)}></img>
</Interactive>
</div>);
};
const filter = this.filter.addCollection('filter');
var pview = filter.addDynamicView('filter');
pview.applySimpleSort('gsx$name');
@ -196,13 +156,9 @@ class DBSearch extends React.Component {
API.cards.mugic.chain()
.find({ 'gsx$name': { '$regex': new RegExp(string, 'i') }})
.where((obj) => {return (obj.gsx$splash != ('') )}).data()
).sort((a, b) => {
a = a.gsx$name.toLowerCase();
b = b.gsx$name.toLowerCase();
if (a < b) return -1;
else if (a > b) return 1;
else return 0;
}).map(thumb_link);
)
.sort(sortCardName)
.map(thumb_link);
// Check Artists
if (content.length == 0) {
@ -222,13 +178,9 @@ class DBSearch extends React.Component {
API.cards.mugic.chain()
.find({ 'gsx$artist': { '$regex': new RegExp(string, 'i') }})
.where((obj) => {return (obj.gsx$splash != ('') )}).data()
).sort((a, b) => {
a = a.gsx$name.toLowerCase();
b = b.gsx$name.toLowerCase();
if (a < b) return -1;
else if (a > b) return 1;
else return 0;
}).map(text_link);
)
.sort((a, b) => (a.gsx$name > b.gsx$name) ? 1 : -1)
.map(text_link);
if (artists.length > 0) {
header = `Art contributed by ${string}:`;
@ -245,7 +197,6 @@ class DBSearch extends React.Component {
return (<div className="results">
<hr />
{names.length > 0 && <>
<div>Entries</div>
<div className="entry_nav">{names}</div>
<hr />
</>}

View File

@ -29,11 +29,11 @@ function Artist(props) {
export default class Single extends React.Component {
@observable fullscreen = false;
expand(e) {
expand = (e) => {
this.fullscreen = true;
}
close(e) {
close = (e) => {
this.fullscreen = false;
}
@ -42,13 +42,15 @@ export default class Single extends React.Component {
return (<>
<div className={"modal" + (this.fullscreen?"":" hidden")}>
<span className="close" onClick={this.close.bind(this)}>&times;</span>
<span className="close" onClick={this.close}>&times;</span>
<img className="modal-content" src={API.base_image + card.gsx$splash} />
</div>
{card.gsx$splash && (
<div className="entry_splash">
{/*<span className="arrow">&#8681;</span>*/}
<img onClick={this.expand.bind(this)} src={API.base_image + card.gsx$splash} />
{card.gsx$splash && (
<img onClick={this.expand} src={API.base_image + card.gsx$splash} />
)}
</div>
)}
<div className="entry_body">
@ -56,62 +58,61 @@ export default class Single extends React.Component {
<Name name={card.gsx$name} />
<hr />
</div>
{this.props.text &&
{this.props.text && (
<div className="nocolumn">{this.props.text}</div>
}
)}
{!this.props.text &&
<div className="column">
{card.gsx$artist && <>
{card.gsx$artist && (<>
<div>
<strong>Artist(s):</strong>
<Artist artist={card.gsx$artist} />
</div>
<hr />
</>}
{card.gsx$set && <>
</>)}
{card.gsx$set && (<>
<div>
<strong>Set: </strong>
{`${API.sets[card.gsx$set]} (${card.gsx$set})`}
</div>
<hr />
</>
}
{card.gsx$rarity && <>
</>)}
{card.gsx$rarity && (<>
<div>
<strong>Rarity: </strong>
<Rarity set={card.gsx$set} rarity={card.gsx$rarity} notext="true" />
{card.gsx$rarity}
</div>
<hr />
</>}
{card.gsx$id && <>
</>)}
{card.gsx$id && (<>
<div>
<strong>Card ID: </strong>
{card.gsx$id}
</div>
</>}
{this.props.col0 && <>
</>)}
{this.props.col0 && (<>
<hr />
{this.props.col0}
</>}
{card.gsx$ability && <>
</>)}
{card.gsx$ability && (<>
<hr />
<div>
<strong>Ability:</strong>
<Ability ability={card.gsx$ability} />
</div>
</>}
{card.gsx$flavortext && <>
</>)}
{card.gsx$flavortext && (<>
<hr />
<div>
<strong>Card Flavor:</strong><br />
{card.gsx$flavortext}
</div>
</>}
{this.props.col1 && <>
</>)}
{this.props.col1 && (<>
<hr />
this.props.col1
</>}
</>)}
</div>
}
{!this.props.text &&

View File

@ -1,15 +1,15 @@
import React from 'react';
import { observable } from "mobx";
import { observer, inject } from 'mobx-react';
import { Link, Route } from 'react-router-dom';
import { Route } from 'react-router-dom';
import API from '../SpreadsheetData';
import Header from './Header';
import Home from './Home';
import Search from './Search';
import { SearchButton } from '../Snippets';
import Category from './Category';
import Tribes from './Tribes';
import Category from './Category/Type';
import Tribes from './Category/Tribe';
import Attack from './Single/Attack';
import Battlegear from './Single/Battlegear';
@ -31,78 +31,22 @@ export default class Base extends React.Component {
}
render() {
const { url } = this.props.match;
return (
<div className="portal">
<Header />
<Routing {...this.props} />
<>
<Route exact path={url} component={Home} />
<Route path={`${url}/Search`} component={Search} />
<Route path={`${url}/Attacks`} render={(props) => <Category {...props} type="Attacks" component={Attack} />} />
<Route path={`${url}/Battlegear`} render={(props) => <Category {...props} type="Battlegear" component={Battlegear} />} />
<Route path={`${url}/Creatures`} render={(props) => <Category {...props} type="Creatures" component={Creature} />} />
<Route path={`${url}/Locations`} render={(props) => <Category {...props} type="Locations" component={Location} />} />
<Route path={`${url}/Mugic`} render={(props) => <Category {...props} type="Mugic" component={Mugic} />} />
{API.tribes.map((tribe, i) => (<Route key={i} path={`${url}/${tribe}`} component={Tribes} />))}
</>
</div>
);
}
}
function Routing(props) {
const { url } = props.match;
return (
<>
<Route exact path={url} component={Home} />
<Route path={`${url}/Attacks`} render={(props) => <Category {...props} type="Attacks" component={Attack} />} />
<Route path={`${url}/Battlegear`} render={(props) => <Category {...props} type="Battlegear" component={Battlegear} />} />
<Route path={`${url}/Creatures`} render={(props) => <Category {...props} type="Creatures" component={Creature} />} />
<Route path={`${url}/Locations`} render={(props) => <Category {...props} type="Locations" component={Location} />} />
<Route path={`${url}/Mugic`} render={(props) => <Category {...props} type="Mugic" component={Mugic} />} />
{API.tribes.map((tribe, i) => (
<Route key={i} path={`${url}/${tribe}`} component={Tribes} />
))}
<Route path={`${url}/Search`} component={Search} />
</>
);
}
function voidClick(e) {
e.preventDefault();
e.stopPropagation();
}
function Header() {
const types = (() => {
return (
<li className="dropdown">
<Link to=" " onClick={voidClick} className="dropbtn">Types</Link>
<div className="dropdown-content">
<Link to="/portal/Attacks">Attacks</Link>
<Link to="/portal/Battlegear">Battlegear</Link>
<Link to="/portal/Creatures">Creatures</Link>
<Link to="/portal/Locations">Locations</Link>
<Link to="/portal/Mugic">Mugic</Link>
</div>
</li>
);
})();
const tribes = API.tribes.map((tribe, i) => {
return (
<li key={i} className="dropdown">
<Link to=" " className="dropbtn" onClick={voidClick}>{tribe}</Link>
<div className="dropdown-content">
<Link to={"/portal/"+tribe}>All</Link>
<Link to={"/portal/Creatures/"+tribe}> Creatures</Link>
<Link to={"/portal/Mugic/"+tribe}> Mugic</Link>
</div>
</li>
);
});
return (
<div className="navbar">
<ul>
<li><Link to="/portal/">Home</Link></li>
<li><Link to="/portal/Search"><SearchButton />Search</Link></li>
{types}
{tribes}
</ul>
</div>
);
}

View File

@ -44,11 +44,11 @@
"inlineSourceMap": true
},
"include": [
"./src"
"./src/components"
],
"exclude": [
"./build",
"./node_modules/*",
"./source/**/*.spec.ts"
"./node_modules",
"./src/**/*.spec.ts"
]
}

View File

@ -6,125 +6,132 @@ const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
require('@babel/register');
const devMode = (process.env.NODE_ENV !== 'production' && process.argv.indexOf('-p') === -1);
module.exports = (env, argv) => {
const devMode = argv.mode === 'development';
module.exports = {
entry: ['@babel/polyfill', './src/index.js'],
const config = {
entry: ['@babel/polyfill', './src/index.js'],
devtool: 'inline-source-map',
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
devServer: {
host: '0.0.0.0',
port: 8000,
publicPath: '/build/',
contentBase: __dirname,
watchContentBase: true,
historyApiFallback: {
index: 'index.html',
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
},
output: {
path: path.resolve(__dirname, 'build'),
filename: '[name].js',
chunkFilename: '[name].js',
publicPath: '/build/',
},
devServer: {
host: '0.0.0.0',
port: 8000,
hot: true,
publicPath: '/build/',
contentBase: __dirname,
watchContentBase: true,
historyApiFallback: {
index: 'index.html',
},
},
optimization: {
minimize: true,
minimizer: [
new TerserWebpackPlugin({
parallel: true,
extractComments: true,
terserOptions: {
parse: {
ecma: 8
},
output: {
comments: false
output: {
path: path.resolve(__dirname, 'build'),
filename: '[name].js',
chunkFilename: '[name].js',
publicPath: '/build/',
},
optimization: {
minimize: true,
minimizer: [
new TerserWebpackPlugin({
parallel: true,
extractComments: true,
terserOptions: {
parse: {
ecma: 8
},
output: {
comments: false
}
}
}
}),
new CssMinimizerPlugin()
],
splitChunks: {
cacheGroups: {
default: false,
vendors: {
}),
new CssMinimizerPlugin()
],
splitChunks: {
cacheGroups: {
default: false,
vendors: {
// name of the chunk
name: 'vendor',
// sync + async chunks
chunks: 'all',
// import file path containing node_modules
test: /[\\/]node_modules[\\/]/,
priority: 20,
},
styles: {
name: 'styles',
test: /\.css$/,
chunks: "all",
enforce: true,
},
common: {
name: 'common',
minChunks: 2,
chunks: 'all',
priority: 10,
reuseExistingChunk: true,
enforce: true,
name: 'vendor',
// sync + async chunks
chunks: 'all',
// import file path containing node_modules
test: /[\\/]node_modules[\\/]/,
priority: 20,
},
styles: {
name: 'styles',
test: /\.css$/,
chunks: "all",
enforce: true,
},
common: {
name: 'common',
minChunks: 2,
chunks: 'all',
priority: 10,
reuseExistingChunk: true,
enforce: true,
},
},
},
},
},
module: {
rules: [
{
test: /\.(js|ts)x?$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
'@babel/typescript',
'@babel/preset-env',
'@babel/preset-react',
'@babel/preset-flow',
],
plugins: [
'@babel/plugin-transform-runtime',
'@babel/plugin-proposal-object-rest-spread',
'@babel/plugin-syntax-dynamic-import',
['@babel/plugin-proposal-decorators', { legacy: true }],
['@babel/plugin-proposal-class-properties', { loose: true }],
['@babel/plugin-transform-computed-properties', { loose: true }],
module: {
rules: [
{
test: /\.(js|ts)x?$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
'@babel/typescript',
'@babel/preset-env',
'@babel/preset-react',
],
plugins: [
'@babel/plugin-transform-runtime',
'@babel/plugin-proposal-object-rest-spread',
'@babel/plugin-syntax-dynamic-import',
['@babel/plugin-proposal-decorators', { legacy: true }],
['@babel/plugin-proposal-class-properties', { loose: true }],
['@babel/plugin-transform-computed-properties', { loose: true }],
],
},
},
{
test: /\.s?[ac]ss$/,
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader',
],
},
},
{
test: /\.s?[ac]ss$/,
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader',
],
},
],
},
],
},
// First array is dev only, second is production
plugins: devMode
? [
] : [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production'),
}),
new MiniCssExtractPlugin({
filename: '[name].css'
}),
],
// First array is dev only, second is production
plugins: devMode
? [
] : [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production'),
}),
new MiniCssExtractPlugin({
filename: '[name].css'
}),
],
};
if (devMode) {
config.devtool = 'inline-source-map';
}
return config;
};