diff --git a/changelog.md b/changelog.md index f4a7300..663b675 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,18 @@ # changelog +### Saturday, 03/12/2016 - v2.6.0 +- Added report back to the edit page +- Changed metaeditor icon +- Added a button to quickly share your brew to reddit :) +- Disabled Partial Page Rendering unless your brew hits 75 pages or longer +- The brew renderer will now try and use your first page to judge the page size of each of your brews. This allows you now to set landscape and other weird sizes and everthing should work fine :) +- UI on the user page improved (thanks u/PalaNolho) +- Fixed lists not breaking across columns (thanks u/tyson-nw) +- Added a table of contents snippet (thanks u/tullisar) +- Added a multicolumn snippet + + + ### Thursday, 01/12/2016 - Added in a snippet for a split table - Added an account nav item to new page diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index b81bbb3..7e1c432 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -1,13 +1,14 @@ -var React = require('react'); -var _ = require('lodash'); -var cx = require('classnames'); +const React = require('react'); +const _ = require('lodash'); +const cx = require('classnames'); -var Markdown = require('naturalcrit/markdown.js'); -var ErrorBar = require('./errorBar/errorBar.jsx'); +const Markdown = require('naturalcrit/markdown.js'); +const ErrorBar = require('./errorBar/errorBar.jsx'); -var PAGE_HEIGHT = 1056 + 30; +const PAGE_HEIGHT = 1056; +const PPR_THRESHOLD = 50; -var BrewRenderer = React.createClass({ +const BrewRenderer = React.createClass({ getDefaultProps: function() { return { text : '', @@ -15,16 +16,23 @@ var BrewRenderer = React.createClass({ }; }, getInitialState: function() { + const pages = this.props.text.split('\\page'); + return { viewablePageNumber: 0, height : 0, isMounted : false, + usePPR : true, + + pages : pages, + usePPR : pages.length >= PPR_THRESHOLD, + errors : [] }; }, - totalPages : 0, height : 0, + pageHeight : PAGE_HEIGHT, componentDidMount: function() { this.updateSize(); @@ -34,7 +42,21 @@ var BrewRenderer = React.createClass({ window.removeEventListener("resize", this.updateSize); }, + componentWillReceiveProps: function(nextProps) { + if(this.refs.pages.firstChild) this.pageHeight = this.refs.pages.firstChild.clientHeight; + + const pages = nextProps.text.split('\\page'); + this.setState({ + pages : pages, + usePPR : pages.length >= PPR_THRESHOLD + }) + }, + updateSize : function() { + setTimeout(()=>{ + if(this.refs.pages.firstChild) this.pageHeight = this.refs.pages.firstChild.clientHeight; + }, 1); + this.setState({ height : this.refs.main.parentNode.clientHeight, isMounted : true @@ -43,12 +65,9 @@ var BrewRenderer = React.createClass({ handleScroll : function(e){ this.setState({ - viewablePageNumber : Math.floor(e.target.scrollTop / PAGE_HEIGHT) + viewablePageNumber : Math.floor(e.target.scrollTop / this.pageHeight) }); }, - //Implement later - scrollToPage : function(pageNumber){ - }, shouldRender : function(pageText, index){ if(!this.state.isMounted) return false; @@ -66,7 +85,15 @@ var BrewRenderer = React.createClass({ renderPageInfo : function(){ return
- {this.state.viewablePageNumber + 1} / {this.totalPages} + {this.state.viewablePageNumber + 1} / {this.state.pages.length} +
+ }, + + renderPPRmsg : function(){ + if(!this.state.usePPR) return; + + return
+ Partial Page Renderer enabled, because your brew is so large. May effect rendering.
}, @@ -81,15 +108,18 @@ var BrewRenderer = React.createClass({ }, renderPages : function(){ - var pages = this.props.text.split('\\page'); - this.totalPages = pages.length; + if(this.state.usePPR){ + return _.map(this.state.pages, (page, index)=>{ + if(this.shouldRender(page, index)){ + return this.renderPage(page, index); + }else{ + return this.renderDummyPage(index); + } + }); + } - return _.map(pages, (page, index)=>{ - if(this.shouldRender(page, index)){ - return this.renderPage(page, index); - }else{ - return this.renderDummyPage(index); - } + return _.map(this.state.pages, (page, index)=>{ + return this.renderPage(page, index); }); }, @@ -101,10 +131,11 @@ var BrewRenderer = React.createClass({ -
+
{this.renderPages()}
{this.renderPageInfo()} + {this.renderPPRmsg()}
} }); diff --git a/client/homebrew/brewRenderer/brewRenderer.less b/client/homebrew/brewRenderer/brewRenderer.less index 8a854dd..c893dba 100644 --- a/client/homebrew/brewRenderer/brewRenderer.less +++ b/client/homebrew/brewRenderer/brewRenderer.less @@ -16,6 +16,17 @@ 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{ diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index f25ec8a..407d9c2 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -82,7 +82,11 @@ const Editor = React.createClass({ render : function(){ return(
- + {this.renderMetadataEditor()} { return
}, + renderShareToReddit : function(){ + if(!this.props.metadata.shareId) return; + + return
+ +
+ + + +
+
+ }, + render : function(){ - console.log(this.props.metadata); return
@@ -140,6 +164,8 @@ const MetadataEditor = React.createClass({
+ {this.renderShareToReddit()} + {this.renderDelete()} diff --git a/client/homebrew/editor/metadataEditor/metadataEditor.less b/client/homebrew/editor/metadataEditor/metadataEditor.less index 89683e0..c3141f0 100644 --- a/client/homebrew/editor/metadataEditor/metadataEditor.less +++ b/client/homebrew/editor/metadataEditor/metadataEditor.less @@ -67,6 +67,11 @@ .button(@red); } } + .reddit.field .value{ + button{ + .button(@purple); + } + } .authors.field .value{ font-size: 0.8em; line-height : 1.5em; diff --git a/client/homebrew/editor/snippetbar/snippetbar.jsx b/client/homebrew/editor/snippetbar/snippetbar.jsx index 2f93fbe..ffccbbf 100644 --- a/client/homebrew/editor/snippetbar/snippetbar.jsx +++ b/client/homebrew/editor/snippetbar/snippetbar.jsx @@ -5,8 +5,8 @@ const cx = require('classnames'); const Snippets = require('./snippets/snippets.js'); -const execute = function(val){ - if(_.isFunction(val)) return val(); +const execute = function(val, brew){ + if(_.isFunction(val)) return val(brew); return val; } @@ -15,6 +15,7 @@ const execute = function(val){ const Snippetbar = React.createClass({ getDefaultProps: function() { return { + brew : '', onInject : ()=>{}, onToggle : ()=>{}, showmeta : false @@ -28,6 +29,7 @@ const Snippetbar = React.createClass({ renderSnippetGroups : function(){ return _.map(Snippets, (snippetGroup)=>{ return - + } @@ -58,6 +60,7 @@ module.exports = Snippetbar; const SnippetGroup = React.createClass({ getDefaultProps: function() { return { + brew : '', groupName : '', icon : 'fa-rocket', snippets : [], @@ -65,7 +68,7 @@ const SnippetGroup = React.createClass({ }; }, handleSnippetClick : function(snippet){ - this.props.onSnippetClick(execute(snippet.gen)); + this.props.onSnippetClick(execute(snippet.gen, this.props.brew)); }, renderSnippets : function(){ return _.map(this.props.snippets, (snippet)=>{ diff --git a/client/homebrew/editor/snippetbar/snippets/snippets.js b/client/homebrew/editor/snippetbar/snippets/snippets.js index 60a0f23..bcb1df9 100644 --- a/client/homebrew/editor/snippetbar/snippets/snippets.js +++ b/client/homebrew/editor/snippetbar/snippets/snippets.js @@ -4,6 +4,7 @@ var MonsterBlockGen = require('./monsterblock.gen.js'); var ClassFeatureGen = require('./classfeature.gen.js'); var FullClassGen = require('./fullclass.gen.js'); var CoverPageGen = require('./coverpage.gen.js'); +var TableOfContentsGen = require('./tableOfContents.gen.js'); module.exports = [ @@ -70,6 +71,12 @@ module.exports = [ gen : "[Click here](#p3) to go to page 3\n" }, + { + name : "Table of Contents", + icon : 'fa-book', + gen : TableOfContentsGen + }, + ] }, diff --git a/client/homebrew/editor/snippetbar/snippets/tableOfContents.gen.js b/client/homebrew/editor/snippetbar/snippets/tableOfContents.gen.js new file mode 100644 index 0000000..448b2f4 --- /dev/null +++ b/client/homebrew/editor/snippetbar/snippets/tableOfContents.gen.js @@ -0,0 +1,72 @@ +const _ = require('lodash'); + +const getTOC = (pages) => { + const add1 = (title, page)=>{ + res.push({ + title : title, + page : page + 1, + children : [] + }); + } + const add2 = (title, page)=>{ + if(!_.last(res)) add1('', page); + _.last(res).children.push({ + title : title, + page : page + 1, + children : [] + }); + } + const add3 = (title, page)=>{ + if(!_.last(res)) add1('', page); + if(!_.last(_.last(res).children)) add2('', page); + _.last(_.last(res).children).children.push({ + title : title, + page : page + 1, + children : [] + }); + } + + let res = []; + _.each(pages, (page, pageNum)=>{ + const lines = page.split('\n'); + _.each(lines, (line) => { + if(_.startsWith(line, '# ')){ + const title = line.replace('# ', ''); + add1(title, pageNum) + } + if(_.startsWith(line, '## ')){ + const title = line.replace('## ', ''); + add2(title, pageNum); + } + if(_.startsWith(line, '### ')){ + const title = line.replace('### ', ''); + add3(title, pageNum); + } + }) + }); + return res; +} + +module.exports = function(brew){ + const pages = brew.split('\\page'); + const TOC = getTOC(pages); + const markdown = _.reduce(TOC, (r, g1, idx1)=>{ + r.push(`- **[${idx1 + 1} ${g1.title}](#p${g1.page})**`) + if(g1.children.length){ + _.each(g1.children, (g2, idx2) => { + r.push(` - [${idx1 + 1}.${idx2 + 1} ${g2.title}](#p${g2.page})`); + if(g2.children.length){ + _.each(g2.children, (g3, idx3) => { + r.push(` - [${idx1 + 1}.${idx2 + 1}.${idx3 + 1} ${g3.title}](#p${g3.page})`); + }); + } + }); + } + return r; + }, []).join('\n'); + + return `
+##### Table Of Contents +${markdown} +
\n`; +} \ No newline at end of file diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index db5adb2..64c61f8 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -193,6 +193,7 @@ const EditPage = React.createClass({ {this.renderSaveButton()} {/**/} + Share diff --git a/client/homebrew/pages/sharePage/sharePage.jsx b/client/homebrew/pages/sharePage/sharePage.jsx index 6bf1e58..c15a8ec 100644 --- a/client/homebrew/pages/sharePage/sharePage.jsx +++ b/client/homebrew/pages/sharePage/sharePage.jsx @@ -5,6 +5,7 @@ const cx = require('classnames'); const Nav = require('naturalcrit/nav/nav.jsx'); const Navbar = require('../../navbar/navbar.jsx'); const PrintLink = require('../../navbar/print.navitem.jsx'); +const ReportIssue = require('../../navbar/issue.navitem.jsx'); //const RecentlyViewed = require('../../navbar/recent.navitem.jsx').viewed; const Account = require('../../navbar/account.navitem.jsx'); @@ -34,10 +35,12 @@ const SharePage = React.createClass({ }, handleControlKeys : function(e){ if(!(e.ctrlKey || e.metaKey)) return; - e.stopPropagation(); - e.preventDefault(); const P_KEY = 80; - if(e.keyCode == P_KEY) window.open(`/print/${this.props.brew.shareId}?dialog=true`, '_blank').focus(); + if(e.keyCode == P_KEY){ + window.open(`/print/${this.props.brew.shareId}?dialog=true`, '_blank').focus(); + e.stopPropagation(); + e.preventDefault(); + } }, render : function(){ @@ -48,6 +51,7 @@ const SharePage = React.createClass({ + {/**/} diff --git a/client/homebrew/pages/userPage/brewItem/brewItem.jsx b/client/homebrew/pages/userPage/brewItem/brewItem.jsx index c74a736..fe694b2 100644 --- a/client/homebrew/pages/userPage/brewItem/brewItem.jsx +++ b/client/homebrew/pages/userPage/brewItem/brewItem.jsx @@ -15,23 +15,39 @@ const BrewItem = React.createClass({ }; }, + renderEditLink: function(){ + if(!this.props.brew.editId) return; + + return + + + }, + render : function(){ const brew = this.props.brew; - return
-

{brew.title}

-

{brew.description}

+ return
+

{brew.title}

+

{brew.description}


-
    -
  • Authors: {brew.authors.join(', ')}
  • -
  • - Last updated: - {moment(brew.updatedAt).fromNow()} -
  • -
  • Views: {brew.views}
  • -
- Share link - {(!!brew.editId ? Edit link : null)} +
+ + {brew.authors.join(', ')} + + + {brew.views} + + + {moment(brew.updatedAt).fromNow()} + +
+ +
+ + + + {this.renderEditLink()} +
} }); diff --git a/client/homebrew/pages/userPage/brewItem/brewItem.less b/client/homebrew/pages/userPage/brewItem/brewItem.less index 2263990..3dcbd50 100644 --- a/client/homebrew/pages/userPage/brewItem/brewItem.less +++ b/client/homebrew/pages/userPage/brewItem/brewItem.less @@ -1,19 +1,60 @@ .brewItem{ + position : relative; display : inline-block; vertical-align : top; - width : 25%; + box-sizing : border-box; + box-sizing : border-box; + overflow : hidden; + width : 48%; + margin-right : 15px; margin-bottom : 15px; + padding : 5px 15px 5px 8px; + padding-right : 15px; + border : 1px solid #c9ad6a; + border-radius : 5px; -webkit-column-break-inside : avoid; page-break-inside : avoid; break-inside : avoid; - p.description{ - overflow : hidden; - width : 90%; - text-overflow : ellipsis; - white-space : nowrap; + h4{ + margin-bottom : 5px; + font-size : 2.2em; } - a{ - margin-right : 10px; + .info{ + font-family : ScalySans; + font-size : 1.2em; + &>span{ + margin-right : 15px; + } + } + &:hover{ + .links{ + opacity : 1; + } + } + &:nth-child(2n + 1){ + margin-right : 0px; + } + .links{ + .animate(opacity); + position : absolute; + top : 0px; + right : 0px; + height : 100%; + width : 2em; + opacity : 0; + background-color : fade(black, 60%); + text-align : center; + a{ + .animate(opacity); + display : block; + margin : 8px 0px; + opacity : 0.6; + font-size : 1.3em; + color : white; + &:hover{ + opacity : 1; + } + } } } \ No newline at end of file diff --git a/client/homebrew/pages/userPage/userPage.jsx b/client/homebrew/pages/userPage/userPage.jsx index 19f2a5c..6d583e9 100644 --- a/client/homebrew/pages/userPage/userPage.jsx +++ b/client/homebrew/pages/userPage/userPage.jsx @@ -10,11 +10,11 @@ const Account = require('../../navbar/account.navitem.jsx'); const BrewItem = require('./brewItem/brewItem.jsx'); const brew = { - title : 'test', + title : 'SUPER Long title woah now', authors : [] } -//const BREWS = _.times(25, ()=>{ return brew}); +const BREWS = _.times(25, ()=>{ return brew}); const UserPage = React.createClass({ @@ -26,9 +26,11 @@ const UserPage = React.createClass({ }, renderBrews : function(brews){ - if(!brews || !brews.length) return
No Brews.
+ if(!brews || !brews.length) return
No Brews.
; - return _.map(brews, (brew, idx) => { + const sortedBrews = _.sortBy(brews, (brew)=>{ return brew.title; }); + + return _.map(sortedBrews, (brew, idx) => { return }); }, diff --git a/client/homebrew/pages/userPage/userPage.less b/client/homebrew/pages/userPage/userPage.less index b2f257a..dcd0d63 100644 --- a/client/homebrew/pages/userPage/userPage.less +++ b/client/homebrew/pages/userPage/userPage.less @@ -17,7 +17,7 @@ .phb{ .noColumns(); height : auto; - min-height : 350px; + min-height : 279.4mm; margin : 20px auto; &::after{ display : none; @@ -27,6 +27,7 @@ font-size : 1.3em; font-style : italic; } + } } } \ No newline at end of file diff --git a/client/homebrew/phbStyle/phb.style.less b/client/homebrew/phbStyle/phb.style.less index 7a5736f..80a9d09 100644 --- a/client/homebrew/phbStyle/phb.style.less +++ b/client/homebrew/phbStyle/phb.style.less @@ -15,7 +15,7 @@ body { counter-reset : phb-page-numbers; } *{ - -webkit-print-color-adjust: exact; + -webkit-print-color-adjust : exact; } .useSansSerif(){ font-family : ScalySans; @@ -332,7 +332,7 @@ body { -moz-column-break-after : always; } //Avoid breaking up - p,ul,blockquote,table{ + p,blockquote,table{ z-index : 15; -webkit-column-break-inside : avoid; column-break-inside : avoid; @@ -351,6 +351,10 @@ body { margin-bottom : 0px; margin-left : 1.5em; } + li{ + -webkit-column-break-inside : avoid; + column-break-inside : avoid; + } } //***************************** // * SPELL LIST @@ -445,4 +449,25 @@ body { } .phb pre+.descriptive{ margin-top : 8px; +} +//***************************** +// * TABLE OF CONTENTS +// *****************************/ +.phb .toc{ + -webkit-column-break-inside : avoid; + column-break-inside : avoid; + a{ + color : black; + text-decoration : none; + &:hover{ + text-decoration : underline; + } + } + ul{ + padding-left : 0; + list-style-type : none; + } + &>ul>li{ + margin-bottom : 10px; + } } \ No newline at end of file diff --git a/package.json b/package.json index 4675d0d..e67844d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "homebrewery", "description": "Create authentic looking D&D homebrews using only markdown", - "version": "2.5.2", + "version": "2.6.0", "scripts": { "build": "node_modules/.bin/gulp prod", "watch": "node_modules/.bin/gulp", diff --git a/phb.standalone.css b/phb.standalone.css index adcf20c..9133af9 100644 --- a/phb.standalone.css +++ b/phb.standalone.css @@ -518,7 +518,6 @@ body { -moz-column-break-after: always; } .phb p, -.phb ul, .phb blockquote, .phb table { z-index: 15; @@ -540,6 +539,10 @@ body { margin-bottom: 0px; margin-left: 1.5em; } +.phb li { + -webkit-column-break-inside: avoid; + column-break-inside: avoid; +} .phb .spellList { font-family: ScalySans; column-count: 4; @@ -627,3 +630,21 @@ body { .phb pre + .descriptive { margin-top: 8px; } +.phb .toc { + -webkit-column-break-inside: avoid; + column-break-inside: avoid; +} +.phb .toc a { + color: black; + text-decoration: none; +} +.phb .toc a:hover { + text-decoration: underline; +} +.phb .toc ul { + padding-left: 0; + list-style-type: none; +} +.phb .toc > ul > li { + margin-bottom: 10px; +} diff --git a/shared/naturalcrit/nav/nav.jsx b/shared/naturalcrit/nav/nav.jsx index 84429a9..6439548 100644 --- a/shared/naturalcrit/nav/nav.jsx +++ b/shared/naturalcrit/nav/nav.jsx @@ -50,13 +50,15 @@ var Nav = { var icon; if(this.props.icon) icon = ; + const props = _.omit(this.props, ['newTab']); + if(this.props.href){ - return + return {this.props.children} {icon} }else{ - return
+ return
{this.props.children} {icon}