0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2026-01-24 14:13:02 +00:00

Compare commits

..

13 Commits

Author SHA1 Message Date
Scott Tolksdorf
570d86448d Adding some notes 2017-06-04 22:04:28 -04:00
Scott Tolksdorf
18d0b68eb0 Moving code between renderer and view 2017-06-04 22:04:28 -04:00
Scott Tolksdorf
74d17f32a5 Merge branch 'randombrew' into home 2017-06-04 22:03:52 -04:00
Scott Tolksdorf
469fa957aa Populate now generates a bunch of rnadom brews 2017-06-04 22:03:36 -04:00
Scott Tolksdorf
4d0ebcb1d8 Adding a logs task 2017-06-04 16:26:50 -04:00
Scott Tolksdorf
10f9ac14c7 Renaming colors and a bunch of other things 2017-06-04 16:04:34 -04:00
Scott Tolksdorf
705adbe2c6 Adding additional rule for fullPage 2017-06-04 15:18:49 -04:00
Scott Tolksdorf
7e7428504e Removed dep on marked, added in a definition list for list types 2017-06-04 12:39:42 -04:00
Scott Tolksdorf
c28647726a Added spelllist, blendmode, and collumn fill auto 2017-06-04 12:05:30 -04:00
Scott Tolksdorf
a30bd79399 Added dropcap style, making page snippet 2017-06-04 11:39:47 -04:00
Scott Tolksdorf
87a9c46202 adding a note 2017-06-04 10:14:33 -04:00
Scott Tolksdorf
380bbd661f Starting on the brew card 2017-05-29 23:39:59 -04:00
Scott Tolksdorf
fa203047da Creating new home page, added new account route 2017-05-28 13:18:46 -04:00
44 changed files with 2044 additions and 311 deletions

View File

@@ -60,7 +60,7 @@ const Homebrew = React.createClass({
'/test_old' : <SharePage />, '/test_old' : <SharePage />,
'*' : <HomePage />, '*' : <HomePage brews={this.props.brews}/>,
}); });
}, },
render : function(){ render : function(){

View File

@@ -48,10 +48,10 @@ const SmartNav = Store.createSmartComponent(React.createClass({
<Nav.section> <Nav.section>
<Items.ContinousSave /> <Items.ContinousSave />
<Items.Issue /> <Items.Issue />
<Nav.item newTab={true} href={'/share/' + Store.getBrew().shareId} color='teal' icon='fa-share-alt'> <Nav.item newTab={true} href={'/share/' + this.props.brew.shareId} color='teal' icon='fa-share-alt'>
Share Share
</Nav.item> </Nav.item>
<Items.Print /> <Items.Print shareId={this.props.brew.shareId} />
<Items.Account /> <Items.Account />
</Nav.section> </Nav.section>
</Navbar> </Navbar>

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 KiB

View File

@@ -4,33 +4,31 @@ const cx = require('classnames');
const Nav = require('naturalcrit/nav/nav.jsx'); const Nav = require('naturalcrit/nav/nav.jsx');
const Navbar = require('../../navbar/navbar.jsx'); const Navbar = require('../../navbar/navbar.jsx');
const PatreonNavItem = require('../../navbar/patreon.navitem.jsx'); const NavItem = require('../../navbar/navitems.js');
const IssueNavItem = require('../../navbar/issue.navitem.jsx');
const RecentNavItem = require('../../navbar/recent.navitem.jsx');
const AccountNavItem = require('../../navbar/account.navitem.jsx');
const BrewInterface = require('homebrewery/brewInterface/brewInterface.jsx'); //const BrewInterface = require('homebrewery/brewInterface/brewInterface.jsx');
const BrewCard = require('homebrewery/brewCard/brewCard.jsx');
//const Actions = require('homebrewery/brew.actions.js');
const Actions = require('homebrewery/brew.actions.js');
//
const HomePage = React.createClass({ const HomePage = React.createClass({
handleSave : function(){ getDefaultProps: function() {
Actions.saveNew(); return {
topBrews : []
};
}, },
renderNavbar : function(){ renderNavbar : function(){
return <Navbar> return <Navbar>
<Nav.section> <Nav.section>
<PatreonNavItem collaspe={true} /> <NavItem.Patreon collaspe={true} />
<IssueNavItem collaspe={true} /> <NavItem.Issue collaspe={true} />
<Nav.item newTab={true} href='/changelog' color='purple' icon='fa-star' collaspe={true}> <Nav.item newTab={true} href='/changelog' color='purple' icon='fa-star' collaspe={true}>
What's new What's new
</Nav.item> </Nav.item>
<RecentNavItem.both /> <NavItem.Recent.both />
<AccountNavItem /> <NavItem.Account />
{/*} {/*}
<Nav.item href='/new' color='green' icon='fa-external-link'> <Nav.item href='/new' color='green' icon='fa-external-link'>
New Brew New Brew
@@ -40,22 +38,58 @@ const HomePage = React.createClass({
</Navbar> </Navbar>
}, },
renderNavigation : function(){
return <div className='navigation'>
<p>
Effortlessly create Authnetic looking D&D homebrews with just text
</p>
<div>
<a className='button new' target='_blank' href='/new'>
<i className='fa fa-magic' />
<h3>New</h3>
<p>This is some sample text</p>
</a>
<a className='button search' target='_blank' href='/search'>
<i className='fa fa-search' />
<h3>Search</h3>
<p>This is some sample text</p>
</a>
</div>
<div>
<a className='button docs' target='_blank' href='/docs'>
<i className='fa fa-book' />
<h3>Docs</h3>
<p>This is some sample text</p>
</a>
<a className='button account' target='_blank' href='/account'>
<i className='fa fa-user' />
<h3>Account</h3>
<p>This is some sample text</p>
</a>
</div>
</div>
},
renderTopBrews : function(){
return <div className='topBrews'>
{_.map(this.props.brews, (brew)=><BrewCard brew={brew} key={brew._id}/>)}
</div>
},
render : function(){ render : function(){
return <div className='homePage page'> return <div className='homePage page'>
{this.renderNavbar()} {this.renderNavbar()}
<div className='content'> <div className='content'>
<BrewInterface /> <div className='hero'>
</div> hero
<h1>The Homebrewery</h1>
<div className={cx('floatingSaveButton', { </div>
//show : Store.getBrewText() !== this.props.welcomeText {this.renderNavigation()}
})} onClick={this.handleSave}> {this.renderTopBrews()}
Save current <i className='fa fa-save' />
</div> </div>
<a href='/new' className='floatingNewButton'>
Create your own <i className='fa fa-magic' />
</a>
</div> </div>
} }
}); });

View File

@@ -1,43 +1,109 @@
@import 'homebrewery/phb_style/phb.fonts.less';
.homePage{ .homePage{
position : relative; position : relative;
a.floatingNewButton{ .hero{
.animate(background-color); // .backgroundScrollAnimation();
position : absolute; height : 400px;
display : block; background-image : url('/assets/homebrew/pages/homePage/fantasy_background.jpg');
right : 70px; background-position : 1% 15%;
bottom : 70px; h1{
z-index : 100; margin-top : 15%;
z-index : 5001; font-family : BookInsanity;
padding : 1em; font-size : 3em;
background-color : @orange; font-weight : 800;
font-size : 1.5em; letter-spacing : 0.3em;
color : white; text-align : center;
text-decoration : none;
box-shadow : 3px 3px 15px black;
&:hover{
background-color : darken(@orange, 20%);
} }
} }
.floatingSaveButton{ .navigation{
.animateAll(); padding : 30px;
position : absolute; background-image : url('/assets/homebrew/pages/homePage/dmg_bg.jpg');
display : block; text-align : center;
right : 200px; &>div{
bottom : 90px; //display : flex;
z-index : 100; margin : 0 auto;
z-index : 5000; // justify-content : center;
padding : 0.8em;
cursor : pointer;
background-color : @blue;
font-size : 0.8em;
color : white;
text-decoration : none;
box-shadow : 3px 3px 15px black;
&:hover{
background-color : darken(@blue, 20%);
} }
&.show{ p{
right : 350px; margin-bottom : 20px;
font-size : 0.8em;
}
a.button{
.animate(background-color);
position : relative;
display : block;
height : 60px;
max-width : 280px;
width : 100%;
margin : 15px;
padding : 20px 30px;
padding-left : 80px;
cursor : pointer;
background-color : fade(@red, 30%);
color : black;
text-align : left;
text-decoration : none;
//flex-grow : 0;
display: inline-block;
i{
position : absolute;
top : 15px;
left : 25px;
font-size : 2em;
//transform-style: preserve-3d;
transform: rotateY(0deg);
}
h3{
display : block;
margin-bottom : 3px;
font-size : 1.2em;
font-weight : 600;
letter-spacing : 0.2em;
}
p{
.fadeOutLeft();
.keep();
opacity : 0;
font-size : 0.8em;
}
&:hover{
background-color : fade(@red, 50%);
p{
.fadeInRight();
}
i{
transform: rotateY(360deg);
.animateAll(0.5s);
}
}
} }
} }
}
.topBrews{
background-image : url('/assets/homebrew/pages/homePage/phb_bg.jpg');
}
}
// .vendor(@property, @value) {
// -webkit-@{property}: @value;
// -khtml-@{property}: @value;
// -moz-@{property}: @value;
// @{property}: @value;
// }
// .backgroundScrollAnimation(){
// @top : -100px;
// .vendor(animation-iteration-count, infinite);
// .createAnimation(backgroundScroll, 60s, linear);
// .backgroundScrollKeyFrames(){
// 0% { background-position: 0 @top}
// 100% { background-position: -1200px @top}
// }
// @-webkit-keyframes backgroundScroll {.backgroundScrollKeyFrames();}
// @-moz-keyframes backgroundScroll {.backgroundScrollKeyFrames();}
// @-ms-keyframes backgroundScroll {.backgroundScrollKeyFrames();}
// @-o-keyframes backgroundScroll {.backgroundScrollKeyFrames();}
// @keyframes backgroundScroll {.backgroundScrollKeyFrames();}
// }

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

View File

@@ -1,6 +1,10 @@
const React = require('react'); const React = require('react');
const _ = require('lodash'); const _ = require('lodash');
const cx = require('classnames'); const cx = require('classnames');
const BrewRenderer = require('homebrewery/brewRenderer/brewRenderer.jsx');
const Markdown = require('homebrewery/markdown.js'); const Markdown = require('homebrewery/markdown.js');
const Headtags = require('vitreum/headtags'); const Headtags = require('vitreum/headtags');
@@ -30,7 +34,7 @@ const PrintPage = React.createClass({
}); });
}catch(e){} }catch(e){}
} }
if(this.props.query.dialog) window.print(); //if(this.props.query.dialog) window.print();
}, },
//TODO: Print page shouldn't replicate functionality in brew renderer //TODO: Print page shouldn't replicate functionality in brew renderer
renderStyle : function(){ renderStyle : function(){
@@ -58,8 +62,9 @@ const PrintPage = React.createClass({
return <div className='printPage'> return <div className='printPage'>
<Headtags.title>{this.state.brew.title}</Headtags.title> <Headtags.title>{this.state.brew.title}</Headtags.title>
{this.renderPrintInstructions()} {this.renderPrintInstructions()}
{this.renderStyle()}
{this.renderPages()} <BrewRenderer text={this.state.brew.text} style={this.state.brew.style} />
</div> </div>
} }
}); });

View File

@@ -9,7 +9,7 @@ const ReportIssue = require('../../navbar/issue.navitem.jsx');
//const RecentlyViewed = require('../../navbar/recent.navitem.jsx').viewed; //const RecentlyViewed = require('../../navbar/recent.navitem.jsx').viewed;
const Account = require('../../navbar/account.navitem.jsx'); const Account = require('../../navbar/account.navitem.jsx');
const BrewRenderer = require('homebrewery/brewRenderer/brewRenderer.jsx'); const BrewView = require('homebrewery/BrewView/BrewView.jsx');
const Utils = require('homebrewery/utils.js'); const Utils = require('homebrewery/utils.js');
const Actions = require('homebrewery/brew.actions.js'); const Actions = require('homebrewery/brew.actions.js');
@@ -56,7 +56,7 @@ const SharePage = React.createClass({
</Nav.section> </Nav.section>
<Nav.section> <Nav.section>
<ReportIssue /> <ReportIssue collaspe={true} />
<PrintLink shareId={brew.shareId} /> <PrintLink shareId={brew.shareId} />
<Nav.item href={'/source/' + brew.shareId} color='teal' icon='fa-code'> <Nav.item href={'/source/' + brew.shareId} color='teal' icon='fa-code'>
source source
@@ -65,7 +65,7 @@ const SharePage = React.createClass({
</Nav.section> </Nav.section>
</Navbar> </Navbar>
<div className='content'> <div className='content'>
<BrewRenderer brew={brew} /> <BrewView brew={brew}/>
</div> </div>
</div> </div>
} }

View File

@@ -3,6 +3,8 @@ const _ = require('lodash');
const cx = require('classnames'); const cx = require('classnames');
const moment = require('moment'); const moment = require('moment');
//TODO: Depriacte
const BrewItem = React.createClass({ const BrewItem = React.createClass({
getDefaultProps: function() { getDefaultProps: function() {
return { return {
@@ -24,6 +26,7 @@ const BrewItem = React.createClass({
}, },
render : function(){ render : function(){
console.log('Brew Item should be depricated');
const brew = this.props.brew; const brew = this.props.brew;
return <div className='brewItem'> return <div className='brewItem'>
<h2>{brew.title}</h2> <h2>{brew.title}</h2>

View File

@@ -9,12 +9,12 @@ const RecentNavItem = require('../../navbar/recent.navitem.jsx');
const Account = require('../../navbar/account.navitem.jsx'); const Account = require('../../navbar/account.navitem.jsx');
const BrewItem = require('./brewItem/brewItem.jsx'); const BrewItem = require('./brewItem/brewItem.jsx');
const brew = { // const brew = {
title : 'SUPER Long title woah now', // title : 'SUPER Long title woah now',
authors : [] // authors : []
} // }
const BREWS = _.times(25, ()=>{ return brew}); // const BREWS = _.times(25, ()=>{ return brew});
const UserPage = React.createClass({ const UserPage = React.createClass({
@@ -29,7 +29,6 @@ const UserPage = React.createClass({
if(!brews || !brews.length) return <div className='noBrews'>No Brews.</div>; if(!brews || !brews.length) return <div className='noBrews'>No Brews.</div>;
const sortedBrews = _.sortBy(brews, (brew)=>{ return brew.title; }); const sortedBrews = _.sortBy(brews, (brew)=>{ return brew.title; });
return _.map(sortedBrews, (brew, idx) => { return _.map(sortedBrews, (brew, idx) => {
return <BrewItem brew={brew} key={idx}/> return <BrewItem brew={brew} key={idx}/>
}); });
@@ -52,8 +51,6 @@ const UserPage = React.createClass({
render : function(){ render : function(){
const brews = this.getSortedBrews(); const brews = this.getSortedBrews();
console.log('user brews', brews);
return <div className='userPage page'> return <div className='userPage page'>
<Navbar> <Navbar>
<Nav.section> <Nav.section>

View File

@@ -3,6 +3,7 @@
"description": "Create authentic looking D&D homebrews using only markdown", "description": "Create authentic looking D&D homebrews using only markdown",
"version": "3.0.0", "version": "3.0.0",
"scripts": { "scripts": {
"logs": "heroku logs -t --app=homebrewery",
"dev": "node scripts/dev.js", "dev": "node scripts/dev.js",
"quick": "node scripts/quick.js", "quick": "node scripts/quick.js",
"build": "node scripts/build.js", "build": "node scripts/build.js",
@@ -29,7 +30,6 @@
"jwt-simple": "^0.5.1", "jwt-simple": "^0.5.1",
"lodash": "^4.17.3", "lodash": "^4.17.3",
"loglevel": "^1.4.1", "loglevel": "^1.4.1",
"marked": "^0.3.5",
"moment": "^2.11.0", "moment": "^2.11.0",
"mongoose": "^4.3.3", "mongoose": "^4.3.3",
"nconf": "^0.8.4", "nconf": "^0.8.4",

View File

@@ -3,18 +3,22 @@ const _ = require('lodash');
const DB = require('../server/db.js'); const DB = require('../server/db.js');
const BrewData = require('../server/brew.data.js'); const BrewData = require('../server/brew.data.js');
const BrewGen = require('../test/brew.gen.js'); //const BrewGen = require('../tests/brew.gen.js');
const BrewGen = require('../shared/homebrewery/snippets/brew/brew.snippet.js');
const BREW_COUNT = 50;
return Promise.resolve() return Promise.resolve()
.then(DB.connect) .then(DB.connect)
.then(BrewData.removeAll) .then(BrewData.removeAll)
.then(() => { .then(() => {
console.log('Adding random brews...'); return _.reduce(_.times(BREW_COUNT, BrewGen.brewModel), (flow, model)=>{
return BrewGen.populateDB(BrewGen.random(50)); return flow.then(()=>BrewData.create(model))
}, Promise.resolve());
}) })
.then(() => { .then(() => {
console.log('Adding specific brews...'); console.log(`Added ${BREW_COUNT} brews`);
return BrewGen.populateDB(BrewGen.static());
}) })
.then(() => { .then(() => {
return DB.close(); return DB.close();

View File

@@ -1,6 +1,6 @@
const _ = require('lodash'); const _ = require('lodash');
module.exports = (Brew) => { module.exports = (BrewModel) => {
const cmds = { const cmds = {
termSearch : (terms='', opts, fullAccess) => { termSearch : (terms='', opts, fullAccess) => {
let query = {}; let query = {};
@@ -34,7 +34,8 @@ module.exports = (Brew) => {
opts.page = _.toNumber(opts.page); opts.page = _.toNumber(opts.page);
let filter = { let filter = {
text : 0 text : 0,
style : 0
}; };
if(!fullAccess){ if(!fullAccess){
@@ -42,7 +43,7 @@ module.exports = (Brew) => {
queryObj.published = true; queryObj.published = true;
} }
const searchQuery = Brew const searchQuery = BrewModel
.find(queryObj) .find(queryObj)
.sort(opts.sort) .sort(opts.sort)
.select(filter) .select(filter)
@@ -51,7 +52,7 @@ module.exports = (Brew) => {
.lean() .lean()
.exec(); .exec();
const countQuery = Brew.count(queryObj).exec(); const countQuery = BrewModel.count(queryObj).exec();
return Promise.all([searchQuery, countQuery]) return Promise.all([searchQuery, countQuery])
.then((result) => { .then((result) => {

View File

@@ -16,6 +16,20 @@ const statics = {
oldTest : fs.readFileSync('./statics/oldTest.brew.md', 'utf8'), oldTest : fs.readFileSync('./statics/oldTest.brew.md', 'utf8'),
}; };
let topBrews = [];
const getTopBrews = ()=>{
//Add in filter of last 2 weeks
return BrewData.search({}, {
limit : 4,
sort : {views : -1}
}, false).then(({brews, total})=>brews);
};
getTopBrews().then((brews)=>{
topBrews=brews;
});
const vitreumRender = require('vitreum/steps/render'); const vitreumRender = require('vitreum/steps/render');
const templateFn = require('../client/template.js'); const templateFn = require('../client/template.js');
@@ -30,9 +44,7 @@ const renderPage = (req, res, next) => {
brews : req.brews, brews : req.brews,
brew : req.brew brew : req.brew
}) })
.then((page) => { .then((page)=>res.send(page))
return res.send(page)
})
.catch(next); .catch(next);
}; };
@@ -54,9 +66,18 @@ router.get('/source/:sharedId', mw.viewBrew, (req, res, next)=>{
}); });
//User Page //User Page
router.get('/account', (req, res, next)=>{
if(req.account && req.account.username){
return res.redirect(`/user/${req.account.username}`);
}else{
return res.redirect(`${config.get('login_path')}?redirect=${encodeURIComponent(req.headers.referer)}`);
}
});
router.get('/user/:username', (req, res, next) => { router.get('/user/:username', (req, res, next) => {
BrewData.search({ user : req.params.username }) const isSelf = req.account && req.params.username == req.account.username;
.then((brews) => {
BrewData.userSearch(req.params.username, isSelf)
.then(({brews, total}) => {
req.brews = brews; req.brews = brews;
return next(); return next();
}) })
@@ -99,7 +120,8 @@ router.get('/new', renderPage);
//Home Page //Home Page
router.get('/', (req, res, next) => { router.get('/', (req, res, next) => {
req.brew = { text : statics.welcomeBrew }; req.brews = topBrews;
console.log(topBrews);
return next(); return next();
}, renderPage); }, renderPage);

View File

@@ -0,0 +1,30 @@
const React = require('react');
const _ = require('lodash');
const cx = require('classnames');
const BrewCard = React.createClass({
getDefaultProps: function() {
return {
brew : {
shareId : '',
title : '',
description : '',
views : 0,
editId : false
}
};
},
render: function(){
const brew = this.props.brew;
return <div className='brewCard'>
<h3>{brew.title}</h3>
<p>{brew.description}</p>
</div>
}
});
module.exports = BrewCard;

View File

@@ -0,0 +1,10 @@
.brewCard{
width : 300px;
height : 100px;
//border : 1px solid black;
background-image : url('/assets/homebrewery/brewCard/monster_bg.jpg');
position : relative;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -2,31 +2,27 @@ const React = require('react');
const _ = require('lodash'); const _ = require('lodash');
const cx = require('classnames'); const cx = require('classnames');
//TODO: Convert old renderer to just be the old markdown parser
const OldBrewRenderer = require('depricated/brewRendererOld/brewRendererOld.jsx'); const OldBrewRenderer = require('depricated/brewRendererOld/brewRendererOld.jsx');
const Markdown = require('homebrewery/markdown.js'); const Markdown = require('homebrewery/markdown.js');
const ErrorBar = require('./errorBar/errorBar.jsx');
const RenderWarnings = require('homebrewery/renderWarnings/renderWarnings.jsx') const PPR_RANGE = 0;
const Store = require('homebrewery/brew.store.js');
const PAGE_HEIGHT = 1056;
const PPR_THRESHOLD = 50;
const BrewRenderer = React.createClass({ const BrewRenderer = React.createClass({
getDefaultProps: function() { getDefaultProps: function() {
return { return {
brew : { text : '',
text : '', style : '',
style : ''
},
version : 2,
//TODO: maybe remove? //usePPR : false // TODO: maybe make this into an page index to render
errors : []
pprPage : false
}; };
}, },
/*
getInitialState: function() { getInitialState: function() {
const pages = this.props.brew.text.split('\\page'); const pages = this.props.brew.text.split('\\page');
@@ -40,8 +36,12 @@ const BrewRenderer = React.createClass({
}, },
height : 0, height : 0,
pageHeight : PAGE_HEIGHT, pageHeight : PAGE_HEIGHT,
*/
lastRender : <div></div>, lastRender : <div></div>,
/*
componentDidMount: function() { componentDidMount: function() {
this.updateSize(); this.updateSize();
window.addEventListener('resize', this.updateSize); window.addEventListener('resize', this.updateSize);
@@ -72,16 +72,14 @@ const BrewRenderer = React.createClass({
}); });
}, },
handleScroll : function(e){
this.setState({ */
viewablePageNumber : Math.floor(e.target.scrollTop / this.pageHeight)
});
},
shouldRender : function(pageText, index){ shouldRender : function(pageText, index){
if(!this.state.isMounted) return false; if(!this.state.isMounted) return false;
var viewIndex = this.state.viewablePageNumber; var viewIndex = this.state.viewablePageNumber;
//TODO: increase range, make into a simple function with lodash
if(index == viewIndex - 1) return true; if(index == viewIndex - 1) return true;
if(index == viewIndex) return true; if(index == viewIndex) return true;
if(index == viewIndex + 1) return true; if(index == viewIndex + 1) return true;
@@ -92,12 +90,8 @@ const BrewRenderer = React.createClass({
return false; return false;
}, },
renderPageInfo : function(){
return <div className='pageInfo'>
{this.state.viewablePageNumber + 1} / {this.state.pages.length}
</div>
},
/*
renderPPRmsg : function(){ renderPPRmsg : function(){
if(!this.state.usePPR) return; if(!this.state.usePPR) return;
@@ -105,18 +99,25 @@ const BrewRenderer = React.createClass({
Partial Page Renderer enabled, because your brew is so large. May effect rendering. Partial Page Renderer enabled, because your brew is so large. May effect rendering.
</div> </div>
}, },
*/
renderDummyPage : function(index){
return <div className='phb v2' id={`p${index + 1}`} key={index}>
<i className='fa fa-spinner fa-spin' />
</div>
},
renderPage : function(pageText, index){ renderPage : function(pageText, index){
return <div className='phb v2' id={`p${index + 1}`} dangerouslySetInnerHTML={{__html:Markdown.render(pageText)}} key={index} /> const html = Markdown.render(pageText);
return <div className='phb v2' id={`p${index + 1}`} dangerouslySetInnerHTML={{__html:html}} key={index} />
},
renderPPR : function(pages, pprPageIndex){
return _.map(pages, (page, index)=>{
if(_.inRange(index, pprPageIndex - PPR_RANGE, pprPageIndex + PPR_RANGE +1)){
this.renderPage(page, index);
}
return <div className='phb v2' id={`p${index + 1}`} key={index} />;
});
}, },
renderPages : function(){ renderPages : function(){
/*
if(this.state.usePPR){ if(this.state.usePPR){
return _.map(this.state.pages, (page, index)=>{ return _.map(this.state.pages, (page, index)=>{
if(this.shouldRender(page, index)){ if(this.shouldRender(page, index)){
@@ -126,38 +127,33 @@ const BrewRenderer = React.createClass({
} }
}); });
} }
if(this.props.errors && this.props.errors.length) return this.lastRender; */
this.lastRender = _.map(this.state.pages, (page, index)=>{ const pages = this.props.text.split('\\page');
return this.renderPage(page, index);
}); console.log(this.props.pprPage);
return this.lastRender;
if(this.props.pprPage !== false) return this.renderPPR(pages, this.props.pprPage);
return _.map(pages, (page, index)=>this.renderPage(page, index));
//TODO: See if you need error handling?
//if(this.props.errors && this.props.errors.length) return this.lastRender;
}, },
//TODO: This is pretty bad //TODO: This is pretty bad
renderStyle : function(){ renderStyle : function(){
return <style>{this.props.brew.style.replace(/;/g, ' !important;')}</style> return <style>{this.props.style.replace(/;/g, ' !important;')}</style>
}, },
render : function(){ render : function(){
if(this.props.brew.version == 1) return <OldBrewRenderer value={this.props.brew.text} />; //TODO: Add in the brew version check
//if(this.props.brew.version == 1) return <OldBrewRenderer value={this.props.brew.text} />;
return <div className='brewRenderer'
onScroll={this.handleScroll}
ref='main'
style={{height : this.state.height}}>
<ErrorBar errors={this.props.errors} />
<RenderWarnings />
return <div className='brewRenderer'>
{this.renderStyle()} {this.renderStyle()}
{this.renderPages()}
<div className='pages' ref='pages'>
{this.renderPages()}
</div>
{this.renderPageInfo()}
{this.renderPPRmsg()}
</div> </div>
} }
}); });

View File

@@ -1,39 +1,2 @@
@import (less) './shared/homebrewery/phb_style/phb.less'; @import (less) './shared/homebrewery/phb_style/phb.less';
.pane{
position : relative;
}
.brewRenderer{
overflow-y : scroll;
.pageInfo{
position : absolute;
right : 17px;
bottom : 0;
z-index : 1000;
padding : 8px 10px;
background-color : #333;
font-size : 10px;
font-weight : 800;
color : white;
}
.ppr_msg{
position : absolute;
left : 0px;
bottom : 0;
z-index : 1000;
padding : 8px 10px;
background-color : #333;
font-size : 10px;
font-weight : 800;
color : white;
}
.pages{
margin : 30px 0px;
&>.phb{
margin-right : auto;
margin-bottom : 30px;
margin-left : auto;
box-shadow : 1px 4px 14px #000;
}
}
}

View File

@@ -0,0 +1,84 @@
const React = require('react');
const _ = require('lodash');
const cx = require('classnames');
//const ErrorBar = require('./errorBar/errorBar.jsx');
const RenderWarnings = require('homebrewery/renderWarnings/renderWarnings.jsx');
//const Store = require('homebrewery/brew.store.js');
const PAGE_HEIGHT = 1056;
const BrewRenderer = require('../brewRenderer/brewRenderer.jsx');
const BrewView = React.createClass({
getDefaultProps: function() {
return {
brew : {
text : '',
style : ''
},
};
},
getInitialState: function() {
const pages = this.props.brew.text.split('\\page');
return {
viewablePageNumber: 0,
//height : 0,
//isMounted : false,
//TODO: Change to page count ?
pages : pages,
};
},
//height : 0,
pageHeight : PAGE_HEIGHT,
componentWillReceiveProps: function(nextProps) {
//if(this.refs.pages && this.refs.pages.firstChild) this.pageHeight = this.refs.pages.firstChild.clientHeight;
const pages = nextProps.brew.text.split('\\page');
this.setState({
pages : pages,
//usePPR : pages.length >= PPR_THRESHOLD
})
},
handleScroll : function(e){
this.setState({
viewablePageNumber : Math.floor(e.target.scrollTop / PAGE_HEIGHT) //this.pageHeight)
});
},
renderPageInfo : function(){
return <div className='pageInfo'>
{this.state.viewablePageNumber + 1} / {this.state.pages.length}
</div>
},
render: function(){
return <div className='brewView' onScroll={this.handleScroll}>
<BrewRenderer
text={this.props.brew.text}
style={this.props.brew.style}
version={this.props.brew.version}
pprPage={2}
/>
{this.renderPageInfo()}
</div>
}
});
module.exports = BrewView;

View File

@@ -0,0 +1,42 @@
.pane{
position : relative;
}
.brewView{
overflow-y : scroll;
height : 100%;
.pageInfo{
position : absolute;
right : 17px;
bottom : 0;
z-index : 1000;
padding : 8px 10px;
background-color : #333;
font-size : 10px;
font-weight : 800;
color : white;
}
/*
.ppr_msg{
position : absolute;
left : 0px;
bottom : 0;
z-index : 1000;
padding : 8px 10px;
background-color : #333;
font-size : 10px;
font-weight : 800;
color : white;
}
*/
.brewRenderer{
margin : 30px 0px;
&>.phb{
margin-right : auto;
margin-bottom : 30px;
margin-left : auto;
box-shadow : 1px 4px 14px #000;
}
}
}

View File

@@ -0,0 +1,11 @@
//const Actions = require('homebrewery/brew.actions.js');
const Store = require('homebrewery/brew.store.js');
const BrewView = require('./brewView.jsx')
module.exports = Store.createSmartComponent(BrewView, ()=>{
return {
brew : Store.getBrew()
};
});

View File

@@ -1,5 +1,6 @@
const _ = require('lodash'); const _ = require('lodash');
const Markdown = require('marked'); //const Markdown = require('marked');
const Markdown = require('./marked.lib.js');
const renderer = new Markdown.Renderer(); const renderer = new Markdown.Renderer();
@@ -10,7 +11,9 @@ renderer.paragraph = function(text){
if(!matches) return `\n<p>${text}</p>\n`; if(!matches) return `\n<p>${text}</p>\n`;
let matchIndex = 0; let matchIndex = 0;
const res = _.reduce(text.split(blockReg), (r, text) => { const res = _.reduce(text.split(blockReg), (r, text) => {
//if(text) r.push(text);
if(text) r.push(Markdown(text, {renderer : renderer, sanitize: true})); if(text) r.push(Markdown(text, {renderer : renderer, sanitize: true}));
const block = matches[matchIndex]; const block = matches[matchIndex];
if(block && block[0] == '{'){ if(block && block[0] == '{'){
r.push(`\n\n<div class="block ${block.substring(2).split(',').join(' ')}">`); r.push(`\n\n<div class="block ${block.substring(2).split(',').join(' ')}">`);
@@ -25,10 +28,14 @@ renderer.paragraph = function(text){
}, []).join('\n'); }, []).join('\n');
return res; return res;
}; };
renderer.image = function(href, title, text){ renderer.image = function(href, title, text){
return `<img src="${href}" class="${text.split(',').join(' ')}"></img>`; return `<img src="${href}" class="${text.split(',').join(' ')}"></img>`;
}; };
renderer.list = function(list, isOrdered, isDef){
if(isDef) return `<ul class='alt'>${list}</ul>`;
if(isOrdered) return `<ol>${list}</ol>`;
return `<ul>${list}</ul>`;
}
module.exports = { module.exports = {
@@ -36,9 +43,12 @@ module.exports = {
render : (rawBrewText)=>{ render : (rawBrewText)=>{
blockCount = 0; blockCount = 0;
rawBrewText = rawBrewText.replace(/\\column/g, '{{columnSplit }}') rawBrewText = rawBrewText.replace(/\\column/g, '{{columnSplit }}');
let html = Markdown(rawBrewText,{renderer : renderer, sanitize: true});
let html = Markdown(rawBrewText, {renderer : renderer, sanitize: true});
//Close all hanging block tags //Close all hanging block tags
html += _.times(blockCount, ()=>{return '</div>'}).join('\n'); html += _.times(blockCount, ()=>{return '</div>'}).join('\n');
return html; return html;

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +1,7 @@
/////////////////// ///////////////////
.spell{ .spell{
ul:first-of-type{
margin-top : -0.5em;
margin-bottom : 0.5em;
list-style-type : none;
&+p{
text-indent : 0em;
}
}
} }
.monster{ .monster{
.breakAvoid(); .breakAvoid();
@@ -23,10 +15,6 @@
tbody tr { background-color: transparent }; tbody tr { background-color: transparent };
} }
ul:nth-of-type(1),ul:nth-of-type(2){ ul:nth-of-type(1),ul:nth-of-type(2){
list-style: none;
padding-left : 1em;
text-indent : -1em;
margin-bottom : 0.5em;
strong{ strong{
color : @crimson; color : @crimson;
} }
@@ -36,6 +24,7 @@
right : 7px; right : 7px;
bottom : 19px; bottom : 19px;
left : 7px; left : 7px;
//TODO: Swap out to variable color
background-color : #FDF1DC; background-color : #FDF1DC;
border-image-slice : 8; border-image-slice : 8;
border-image-source : @monsterBorder; border-image-source : @monsterBorder;
@@ -43,6 +32,7 @@
} }
&.wide{ &.wide{
column-count : 2; column-count : 2;
column-fill:auto;
} }
} }
.note{ .note{
@@ -104,7 +94,7 @@
z-index : 150; z-index : 150;
width : 200px; width : 200px;
font-size : 0.9em; font-size : 0.9em;
color : @gold; color : @brown;
text-align : right; text-align : right;
} }
//***************************** //*****************************
@@ -161,38 +151,44 @@
} }
.wide{ .wide{
column-span : all; column-span : all;
-webkit-column-span : all; }
-moz-column-span : all; .fullPage, .full{
column-span : all;
height: 100%;
} }
.oneColumn{ .oneColumn{
column-count : 1; column-count : 1;
column-fill:auto;
// column-gap : 1cm; // column-gap : 1cm;
} }
.twoColumn{ .twoColumn{
column-count : 2; column-count : 2;
column-fill:auto;
//column-fill: auto; //column-fill: auto;
////column-gap : 1cm; ////column-gap : 1cm;
} }
.threeColumn{ .threeColumn{
column-count : 3; column-count : 3;
column-fill:auto;
//column-gap : 1cm; //column-gap : 1cm;
} }
.fourColumn{ .fourColumn{
column-count : 4; column-count : 4;
//column-gap : 1cm; //column-gap : 1cm;
column-fill:auto;
} }
.columnSplit{ .columnSplit{
visibility : hidden; visibility : hidden;
-webkit-column-break-bfore : always; -webkit-column-break-bfore : always;
break-before : column; break-before : column;
} }
.brushed{ // .brushed{
border-image-outset : 25px 17px; // border-image-outset : 25px 17px;
border-image-repeat : round; // border-image-repeat : round;
border-image-slice : 1250 1250 1250 1250; // border-image-slice : 1250 1250 1250 1250;
border-image-width : 1250px; // border-image-width : 1250px;
border-image-source : url('http : //i.imgur.com/nzPYZyD.png'); // border-image-source : url('http://i.imgur.com/nzPYZyD.png');
} // }
//basics //basics
.left{ .left{
text-align : left; text-align : left;
@@ -208,4 +204,13 @@
} }
.sansSerif{ .sansSerif{
.useSansSerif(); .useSansSerif();
}
.dropcap{
p::first-letter{
float : left;
font-family : Solbera;
font-size : 10em;
color : #222;
line-height : 0.8em;
}
} }

View File

@@ -1,5 +1,13 @@
//TODO: come up with fun color names //TODO: come up with fun color names
@crimson : #58180D;
@red : #9c2b1b;
@brown : #c9ad6a; //brown?
@green : #e0e5c1;
@yellow : #faf7ea; //same as background?
@teal : blue;
@blue : blue;
@background : #EEE5CE; @background : #EEE5CE;
@noteGreen : #e0e5c1; @noteGreen : #e0e5c1;
@headerUnderline : #c9ad6a; @headerUnderline : #c9ad6a;
@@ -20,13 +28,7 @@
} }
} }
@crimson : #58180D;
@red : #9c2b1b;
@gold : #c9ad6a; //brown?
@green : #e0e5c1;
@yellow : #faf7ea; //same as background?
@teal : blue;
@blue : blue;
//TODO make a color mixin generator //TODO make a color mixin generator
@@ -34,5 +36,6 @@
.blue{ .colorElements(@blue); } .blue{ .colorElements(@blue); }
.green{ .colorElements(@green); } .green{ .colorElements(@green); }
.yellow{ .colorElements(@yellow); } .yellow{ .colorElements(@yellow); }
.gold{ .colorElements(@gold); } .brown{ .colorElements(fade(@brown, 50%)); }
.red{ .colorElements(@red); } .red{ .colorElements(fade(@red, 25%)); }
.crimson{ .colorElements(fade(@crimson, 20%)); }

View File

@@ -1,15 +1,14 @@
pre{ pre{
font-family : monospace; padding : 12px;
background-color : @yellow; background-color : @yellow;
padding : 12px; font-family : monospace;
border: 1px solid #bfbfbf; color : #333;
white-space: pre-wrap; border : 1px solid #bfbfbf;
color : #333; white-space : pre-wrap;
-webkit-column-break-inside : avoid; -webkit-column-break-inside : avoid;
column-break-inside : avoid; column-break-inside : avoid;
} }
hr{ hr{
visibility : visible; visibility : visible;
height : 6px; height : 6px;
@@ -18,8 +17,6 @@ hr{
background-size : 100% 100%; background-size : 100% 100%;
border : none; border : none;
} }
p{ p{
padding-bottom : 0.8em; padding-bottom : 0.8em;
line-height : 1.3em; line-height : 1.3em;
@@ -27,35 +24,42 @@ p{
margin-top : -0.8em; margin-top : -0.8em;
} }
} }
blockquote{ blockquote{
font-style : italic; font-style : italic;
&>p{ &>p{
line-height: 1.8em; line-height : 1.8em;
//Why did I do this?
&:first-child::first-line{ &:first-child::first-line{
font-family : ScalySansSmallCaps;
//TODO: Find the right font for block quotes //TODO: Find the right font for block quotes
font-style: normal; font-style : normal;
font-family: ScalySansSmallCaps;
} }
} }
.cite{ .cite{
font-style: normal; font-style : normal;
text-align: right; text-align : right;
}
}
// IMAGE
img{
display : block;
z-index : -1;
mix-blend-mode : multiply;
&.center{
margin-right : auto;
margin-left : auto;
}
&.noBlend{
mix-blend-mode : normal;
}
&.bg, &.background{
position : absolute;
} }
} }
//Indents after p or lists //Indents after p or lists
p+p, ul+p, ol+p{ p+p, ul+p, ol+p{
text-indent : 1em; text-indent : 1em;
} }
img{
z-index : -1;
}
strong{ strong{
font-weight : bold; font-weight : bold;
letter-spacing : 0.03em; letter-spacing : 0.03em;
@@ -88,13 +92,6 @@ h1{
font-size : 0.987cm; font-size : 0.987cm;
-webkit-column-span : all; -webkit-column-span : all;
-moz-column-span : all; -moz-column-span : all;
&+p::first-letter{
float : left;
font-family : Solbera;
font-size : 10em;
color : #222;
line-height : 0.8em;
}
} }
h2{ h2{
font-size : 0.705cm; font-size : 0.705cm;
@@ -113,8 +110,6 @@ h5{
font-size : 0.423cm; font-size : 0.423cm;
font-weight : 900; font-weight : 900;
} }
//****************************** //******************************
// LISTS // LISTS
//****************************** //******************************
@@ -141,7 +136,19 @@ ol{
list-style-type : decimal; list-style-type : decimal;
} }
p+ul.alt{
margin-top : -0.5em;
}
ul.alt{
margin-bottom : 0.5em;
padding-left : 0em;
list-style-position : outside;
list-style-type : none;
list-style-type : none;
&+p{
text-indent : 0em;
}
}
//***************************** //*****************************
// * TABLE // * TABLE
// *****************************/ // *****************************/
@@ -150,6 +157,7 @@ table{
width : 100%; width : 100%;
margin-bottom : 1em; margin-bottom : 1em;
font-size : 10pt; font-size : 10pt;
break-inside : avoid-column;
thead{ thead{
font-weight : 800; font-weight : 800;
th{ th{

View File

@@ -57,7 +57,7 @@
background-size : cover; background-size : cover;
padding: 28px 63px; padding: 28px 63px;
box-sizing: border-box; box-sizing: border-box;
color : lighten(@gold, 0%); color : lighten(@brown, 0%);
font-size: 0.7em; font-size: 0.7em;
} }
&:nth-child(even){ &:nth-child(even){
@@ -81,7 +81,7 @@
bottom : 22px; bottom : 22px;
width : 50px; width : 50px;
font-size : 0.9em; font-size : 0.9em;
color : @gold; color : @brown;
text-align : center; text-align : center;
} }

View File

@@ -0,0 +1,74 @@
const _ = require('lodash');
const Data = require('./random.data.js');
const Snips = _.merge(
require('./spell.snippet.js'),
require('./table.snippet.js'),
require('./class.snippet.js'),
require('./note.snippet.js'),
require('./monster.snippet.js')
);
const BrewSnippets = {
brewModel : ()=>{
return {
title : Data.rand(Data.titles),
description : Data.rand(Data.subtitles),
text : BrewSnippets.brew(),
authors : _.sampleSize(['userA','userB','userC','userD'], _.random(0, 3)),
systems : _.sampleSize(['5e', '4e', '3.5e', 'Pathfinder'], _.random(0,2)),
views : _.random(0,1000),
published : !!_.random(0,1)
}
},
brew : ()=>{
return _.times(_.random(1,10), ()=>_.sample([
BrewSnippets.page1,
BrewSnippets.page2
])()).join('\n\n\\page\n\n');
},
page1 : ()=>{
return BrewSnippets.filler(_.random(10, 15), [Snips.monster, Snips.table]);
},
page2 : ()=>{
const title = '# ' + Data.rand('titles');
let table = Snips.noncasterTable();
if(Data.chance(3)){
table = Snips.casterTable();
if(Data.chance(2)) table = Snips.halfcasterTable();
return `${title}\n\n${table}\n\n${BrewSnippets.paragraph(true)}\n\n${BrewSnippets.filler(3)}`;
}
return `${title}\n\n${table}\n\n${BrewSnippets.paragraph(true)}\n\n${BrewSnippets.filler(5)}`;
},
filler : (count = 1, additional = [])=>{
const base = _.concat([
BrewSnippets.paragraph, BrewSnippets.paragraph, BrewSnippets.paragraph, BrewSnippets.paragraph,
BrewSnippets.paragraph, BrewSnippets.paragraph, BrewSnippets.paragraph, BrewSnippets.paragraph,
Snips.table,
Snips.note, Snips.note, Snips.altnote
], additional);
return _.times(count, ()=>{
let res = _.sample(base)();
if(Data.chance(8)) res = BrewSnippets.title() + '\n\n' + res;
return res;
}).join('\n\n');
},
paragraph : (dropcap = false)=>{
let res = Data.rand(Data.sentences, 6, 3).join(' ');
if(dropcap || Data.chance(20)) res = `{{dropcap\n${res}\n}}`;
return res;
},
title : ()=>{
return _.sample(['##', '###', '##', '###','####', '#####']) + ' ' + Data.rand('titles');
}
}
module.exports = BrewSnippets;

View File

@@ -11,6 +11,52 @@ const getFeature = (level)=>{
return res.join(', '); return res.join(', ');
}; };
const spellLevels = [
[2,'―','―','―','―','―','―','―','―'],
[3,'―','―','―','―','―','―','―','―'],
[4, 2 ,'―','―','―','―','―','―','―'],
[4, 3 ,'―','―','―','―','―','―','―'],
[4, 3 , 2 ,'―','―','―','―','―','―'],
[4, 3 , 3 ,'―','―','―','―','―','―'],
[4, 3 , 3 , 1 ,'―','―','―','―','―'],
[4, 3 , 3 , 2 ,'―','―','―','―','―'],
[4, 3 , 3 , 3 , 1 ,'―','―','―','―'],
[4, 3 , 3 , 3 , 2 ,'―','―','―','―'],
[4, 3 , 3 , 3 , 2 , 1 ,'―','―','―'],
[4, 3 , 3 , 3 , 2 , 1 ,'―','―','―'],
[4, 3 , 3 , 3 , 2 , 1 , 1 ,'―','―'],
[4, 3 , 3 , 3 , 2 , 1 , 1 ,'―','―'],
[4, 3 , 3 , 3 , 2 , 1 , 1 , 1 ,'―'],
[4, 3 , 3 , 3 , 2 , 1 , 1 , 1 ,'―'],
[4, 3 , 3 , 3 , 2 , 1 , 1 , 1 , 1 ],
[4, 3 , 3 , 3 , 3 , 1 , 1 , 1 , 1 ],
[4, 3 , 3 , 3 , 3 , 2 , 1 , 1 , 1 ],
[4, 3 , 3 , 3 , 3 , 2 , 2 , 1 , 1 ]
];
const halfspellLevels = [
['―','―','―','―','―'],
[ 2 ,'―','―','―','―'],
[ 3 ,'―','―','―','―'],
[ 3 ,'―','―','―','―'],
[ 4 , 2 ,'―','―','―'],
[ 4 , 2 ,'―','―','―'],
[ 4 , 3 ,'―','―','―'],
[ 4 , 3 ,'―','―','―'],
[ 4 , 3 , 2 ,'―','―'],
[ 4 , 3 , 2 ,'―','―'],
[ 4 , 3 , 3 ,'―','―'],
[ 4 , 3 , 3 ,'―','―'],
[ 4 , 3 , 3 , 1 ,'―'],
[ 4 , 3 , 3 , 1 ,'―'],
[ 4 , 3 , 3 , 2 ,'―'],
[ 4 , 3 , 3 , 2 ,'―'],
[ 4 , 3 , 3 , 3 , 1 ],
[ 4 , 3 , 3 , 3 , 1 ],
[ 4 , 3 , 3 , 3 , 2 ],
[ 4 , 3 , 3 , 3 , 2 ]
];
module.exports = { module.exports = {
@@ -23,13 +69,15 @@ module.exports = {
lvlText, lvlText,
'+'+Math.floor(level/4 + 2), '+'+Math.floor(level/4 + 2),
getFeature(level), getFeature(level),
'+'+featureScore '??'
].join(' | ') + ' |'; ].join(' | ') + ' | ' +
spellLevels[level].join(' | ')
+ ' |';
}).join('\n'); }).join('\n');
return `{{frame,wide return `{{frame,wide
##### ${Data.rand('classes')} ##### ${Data.rand('classes')}
| Level | Proficiency Bonus | Features | Cantrips Known | Spells Known | 1st | 2nd | 3rd | 4th | 5th | 6th | 7th | 8th | 9th | | Level | Proficiency Bonus | Features | Spells Known | 1st | 2nd | 3rd | 4th | 5th | 6th | 7th | 8th | 9th |
|:---:|:---:|:---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:| |:---:|:---:|:---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
${rows} ${rows}
}}`; }}`;
@@ -43,9 +91,10 @@ ${rows}
return '| ' + [ return '| ' + [
lvlText, lvlText,
'+'+Math.floor(level/4 + 2), '+'+Math.floor(level/4 + 2),
getFeature(level), getFeature(level)
'+'+featureScore ].join(' | ') + ' | ' +
].join(' | ') + ' |'; halfspellLevels[level].join(' | ')
+ ' |'
}).join('\n'); }).join('\n');

View File

@@ -6,7 +6,11 @@ module.exports = _.merge(
require('./class.snippet.js'), require('./class.snippet.js'),
require('./note.snippet.js'), require('./note.snippet.js'),
require('./monster.snippet.js'), require('./monster.snippet.js'),
require('./toc.snippet.js') require('./toc.snippet.js'),
//require('./random.brew.js')
require('./brew.snippet.js')
//wide //wide

View File

@@ -12,13 +12,10 @@ const getStats = function(){
const getAttributes = ()=>{ const getAttributes = ()=>{
return ` return `
- **Saving Throws** - **Saving Throws**
- **Condition Immunities** " + genList(["groggy", "swagged", "weak-kneed", "buzzed", "groovy", "melancholy", "drunk"], 3), - **Condition Immunities** ${Data.rand(["groggy", "swagged", "weak-kneed", "buzzed", "groovy", "melancholy", "drunk"], 3).join(', ')},
- **Senses** passive Perception " + _.random(3, 20), - **Senses** passive Perception " ${_.random(3, 20)},
- **Languages** ${Data.rand(["Common", "Pottymouth", "Gibberish", "Latin", "Jive"], 2).join(', ')} - **Languages** ${Data.rand(["Common", "Pottymouth", "Gibberish", "Latin", "Jive"], 2).join(', ')}
- **Challenge** ${_.random(0, 15)} (${_.random(10,10000)} XP) - **Challenge** ${_.random(0, 15)} (${_.random(10,10000)} XP)
`; `;
@@ -45,23 +42,16 @@ module.exports = {
*${Data.rand('sizes')}, ${Data.rand('alignments')}* *${Data.rand('sizes')}, ${Data.rand('alignments')}*
--- ---
- **Armor Class** ${_.random(10,20)} - **Armor Class** ${_.random(10,20)}
- **Hit Points** ${_.random(1, 150)} (1d4 + 5) - **Hit Points** ${_.random(1, 150)} (1d4 + 5)
- **Speed** ${ _.random(0,50)} ft - **Speed** ${ _.random(0,50)} ft
--- ---
|STR|DEX|CON|INT|WIS|CHA| |STR|DEX|CON|INT|WIS|CHA|
|:---:|:---:|:---:|:---:|:---:|:---:| |:---:|:---:|:---:|:---:|:---:|:---:|
${getStats()} ${getStats()}
--- ---
${getAttributes()} ${getAttributes()}
--- ---
Abilities Abilities

View File

@@ -4,7 +4,7 @@ const Data = require('./random.data.js');
module.exports = { module.exports = {
note : ()=>{ note : ()=>{
return `{{note return `{{note,red
##### ${Data.rand('abilities')} ##### ${Data.rand('abilities')}
${Data.rand('sentences', 6, 4).join(' ')} ${Data.rand('sentences', 6, 4).join(' ')}
}}` }}`

View File

@@ -0,0 +1,11 @@
const _ = require('lodash');
const Data = require('./random.data.js');
module.exports = {
brew : ()=>{
}
}

View File

@@ -5,7 +5,9 @@ const Data = {
const data = (Data[name] ? Data[name] : name); const data = (Data[name] ? Data[name] : name);
return _.sampleSize(data, _.random(min, max)); return _.sampleSize(data, _.random(min, max));
}, },
//Boolean of 1 in n chance
chance : (max = 20)=>_.random(1,max)== 1,
mix : (list, max = 1, min = 1)=>_.times(_.random(min, max), ()=>_.sample(list)),
titles : [ titles : [
`The Burning Gallows`, `The Burning Gallows`,
`The Ring of Nenlast`, `The Ring of Nenlast`,

View File

@@ -26,7 +26,7 @@ module.exports = {
const description = Data.rand('effects', 2).concat(Data.rand('effects2')).join(' '); const description = Data.rand('effects', 2).concat(Data.rand('effects2')).join(' ');
return `{{spell return `
#### ${_.sample(Data.spellNames)} #### ${_.sample(Data.spellNames)}
*${_.sample(levels)}-level ${_.sample(schools)}* *${_.sample(levels)}-level ${_.sample(schools)}*
- **Casting Time:** ${_.sample(['1 action', 'Reaction', '10 minutes', '1 hour'])} - **Casting Time:** ${_.sample(['1 action', 'Reaction', '10 minutes', '1 hour'])}
@@ -34,8 +34,18 @@ module.exports = {
- **Components:** ${components} - **Components:** ${components}
- **Duration:** ${duration} - **Duration:** ${duration}
${description} ${description}`;
}}`;
},
spellList : ()=>{
const levels = ['Cantrips (0 Level)', '2nd Level', '3rd Level', '4th Level', '5th Level', '6th Level', '7th Level', '8th Level', '9th Level'];
const content = _.map(levels, (level)=>{
const spells = _.map(Data.rand('spellNames', 15, 5), (spell)=>`- ${spell}`).join('\n');
return `##### ${level} \n${spells} \n`;
}).join('\n');
return `{{fourColumn,fullPage,sansSerif\n${content}\n}}`;
} }
} }

View File

@@ -43,15 +43,26 @@ const columns = {
module.exports = { module.exports = {
table : () => { table : () => {
let title = '';
if(Data.chance(5)) title = `##### ${Data.rand(Data.abilities)}\n`;
const rows = _.sample([4,6,8,10]); const rows = _.sample([4,6,8,10]);
const cols = [ let fns = [];
columns.roll(rows), if(Data.chance(3)) fns.push(columns.roll);
columns.level(rows),
columns.gear(rows)
];
return _.times(rows + 2, (i)=>{ fns = _.concat(fns, Data.rand([
columns.level,
columns.spell,
columns.cost,
columns.gear
], 3, 2 - fns.length))
const cols = _.map(fns, (fn)=>fn(rows));
return title + _.times(rows + 2, (i)=>{
if(i==1){ if(i==1){
return '|' + _.map(cols, (col)=>col[i]).join('|') + '|'; return '|' + _.map(cols, (col)=>col[i]).join('|') + '|';
}else{ }else{

View File

@@ -7,7 +7,7 @@ const config = require('nconf');
const app = require('app.js'); const app = require('app.js');
const DB = require('db.js'); const DB = require('db.js');
const BrewData = require('brew.data.js'); const BrewData = require('brew.data.js');
const BrewGen = require('./brew.gen.js'); const SampleBrews = require('./sample_brews.js');
const Error = require('error.js'); const Error = require('error.js');
@@ -25,7 +25,7 @@ describe('Brew API', () => {
before('Connect DB', DB.connect); before('Connect DB', DB.connect);
before('Clear DB', BrewData.removeAll); before('Clear DB', BrewData.removeAll);
before('Populate brews', ()=>{ before('Populate brews', ()=>{
return BrewGen.populateDB(BrewGen.static()); return SampleBrews.populateDB(SampleBrews.static());
}); });
describe('Create', () => { describe('Create', () => {
it('creates a new brew', () => { it('creates a new brew', () => {
@@ -57,7 +57,7 @@ describe('Brew API', () => {
describe('Update', () => { describe('Update', () => {
it('updates an existing brew', () => { it('updates an existing brew', () => {
const storedBrew = BrewGen.get('BrewA'); const storedBrew = SampleBrews.get('BrewA');
return request(app) return request(app)
.put(`/api/brew/${storedBrew.editId}`) .put(`/api/brew/${storedBrew.editId}`)
.send({ text : 'New Text' }) .send({ text : 'New Text' })
@@ -72,7 +72,7 @@ describe('Brew API', () => {
}); });
it('adds the user as author', () => { it('adds the user as author', () => {
const storedBrew = BrewGen.get('BrewA'); const storedBrew = SampleBrews.get('BrewA');
return request(app) return request(app)
.put(`/api/brew/${storedBrew.editId}`) .put(`/api/brew/${storedBrew.editId}`)
.set('Cookie', `nc_session=${UserXToken}`) .set('Cookie', `nc_session=${UserXToken}`)
@@ -85,7 +85,7 @@ describe('Brew API', () => {
}); });
}); });
it('should throw error on bad edit id', ()=>{ it('should throw error on bad edit id', ()=>{
const storedBrew = BrewGen.get('BrewA'); const storedBrew = SampleBrews.get('BrewA');
return request(app) return request(app)
.put(`/api/brew/BADEDITID`) .put(`/api/brew/BADEDITID`)
.send({ text : 'New Text' }) .send({ text : 'New Text' })
@@ -95,7 +95,7 @@ describe('Brew API', () => {
describe('Remove', () => { describe('Remove', () => {
it('should removes a brew', ()=>{ it('should removes a brew', ()=>{
const storedBrew = BrewGen.get('BrewA'); const storedBrew = SampleBrews.get('BrewA');
return request(app) return request(app)
.del(`/api/brew/${storedBrew.editId}`) .del(`/api/brew/${storedBrew.editId}`)
.send() .send()
@@ -116,7 +116,7 @@ describe('Brew API', () => {
before('Connect DB', DB.connect); before('Connect DB', DB.connect);
before('Clear DB', BrewData.removeAll); before('Clear DB', BrewData.removeAll);
before('Populate brews', ()=>{ before('Populate brews', ()=>{
return BrewGen.populateDB(BrewGen.static()); return SampleBrews.populateDB(SampleBrews.static());
}); });
it('should be able to search for all published brews', ()=>{ it('should be able to search for all published brews', ()=>{
@@ -187,7 +187,7 @@ describe('Brew API', () => {
.expect(200) .expect(200)
.then((res) => { .then((res) => {
const result = res.body; const result = res.body;
const brewCount = _.size(BrewGen.static()); const brewCount = _.size(SampleBrews.static());
result.total.should.be.equal(brewCount); result.total.should.be.equal(brewCount);
result.brews.length.should.be.equal(brewCount); result.brews.length.should.be.equal(brewCount);
result.brews[0].should.have.property('editId'); result.brews[0].should.have.property('editId');
@@ -199,7 +199,7 @@ describe('Brew API', () => {
before('Connect DB', DB.connect); before('Connect DB', DB.connect);
before('Clear DB', BrewData.removeAll); before('Clear DB', BrewData.removeAll);
before('Populate brews', ()=>{ before('Populate brews', ()=>{
return BrewGen.populateDB(BrewGen.static()); return SampleBrews.populateDB(SampleBrews.static());
}); });
it('should be able to query brews for a specific user', ()=>{ it('should be able to query brews for a specific user', ()=>{

View File

@@ -6,20 +6,20 @@ let PopulatedBrews = {};
module.exports = { module.exports = {
//TODO: Add in a generator for old brews to test the old rendering code //TODO: Add in a generator for old brews to test the old rendering code
random : (num = 20)=>{ // random : (num = 20)=>{
return _.times(num, ()=>{ // return _.times(num, ()=>{
//TODO: Build better generator, use new snippets? // //TODO: Build better generator, use new snippets?
return { // return {
title : 'BrewA', // title : 'BrewA',
description : '', // description : '',
text : '', // text : '',
authors : _.sampleSize(['userA','userB','userC','userD'], _.random(0, 3)), // authors : _.sampleSize(['userA','userB','userC','userD'], _.random(0, 3)),
systems : _.sampleSize(['5e', '4e', '3.5e', 'Pathfinder'], _.random(0,2)), // systems : _.sampleSize(['5e', '4e', '3.5e', 'Pathfinder'], _.random(0,2)),
views : _.random(0,1000), // views : _.random(0,1000),
published : !!_.random(0,1) // published : !!_.random(0,1)
}; // };
}); // });
}, // },
old : () => { old : () => {
return [ return [
{ {

View File

@@ -3,7 +3,7 @@ const _ = require('lodash');
const DB = require('db.js'); const DB = require('db.js');
const BrewData = require('brew.data.js'); const BrewData = require('brew.data.js');
const BrewGen = require('./brew.gen.js'); const SampleBrews = require('./sample_brews.js');
//const Error = require('error.js'); //const Error = require('error.js');
@@ -12,7 +12,7 @@ describe('Brew Search', () => {
before('Connect DB', DB.connect); before('Connect DB', DB.connect);
before('Clear DB', BrewData.removeAll); before('Clear DB', BrewData.removeAll);
before('Populate brews', ()=>{ before('Populate brews', ()=>{
return BrewGen.populateDB(BrewGen.static()); return SampleBrews.populateDB(SampleBrews.static());
}); });
@@ -28,7 +28,7 @@ describe('Brew Search', () => {
it('should be able to search for all brews', ()=>{ it('should be able to search for all brews', ()=>{
return BrewData.search() return BrewData.search()
.then((result) => { .then((result) => {
const brewCount = _.size(BrewGen.static()); const brewCount = _.size(SampleBrews.static());
result.total.should.be.equal(brewCount); result.total.should.be.equal(brewCount);
result.brews.length.should.be.equal(brewCount); result.brews.length.should.be.equal(brewCount);
}) })
@@ -41,7 +41,7 @@ describe('Brew Search', () => {
limit : 2 limit : 2
}) })
.then((result) => { .then((result) => {
result.total.should.be.equal(_.size(BrewGen.static())); result.total.should.be.equal(_.size(SampleBrews.static()));
result.brews.length.should.be.equal(2); result.brews.length.should.be.equal(2);
}) })
}); });

View File

@@ -10,7 +10,7 @@ const config = require('nconf')
const Chai = require('chai') const Chai = require('chai')
.use(require('chai-as-promised')) .use(require('chai-as-promised'))
.use(require('chai-subset')) .use(require('chai-subset'))
.use(require('./brew.gen.js').chaiPlugin); .use(require('./sample_brews.js').chaiPlugin);
const log = require('loglevel'); const log = require('loglevel');
log.setLevel(config.get('log_level')); log.setLevel(config.get('log_level'));