0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2026-01-28 04:59:44 +00:00

Merge pull request #1280 from naturalcrit/master

Send v2.11.0 live
This commit is contained in:
Trevor Buckner
2021-03-13 21:53:49 -05:00
committed by GitHub
41 changed files with 594 additions and 2350 deletions

View File

@@ -1,13 +1,32 @@
<style>
h5 {
font-size: .35cm !important;
}
</style>
# changelog # changelog
### Saturday, 13/3/2021 - v2.11.0
- Many background things for upcoming v3. Get pumped.
##### G-Ambatte :
- Fixed new brews failing to save when auto-generated file name is too long.
- "New" button added to the Nav bar.
- "Download" button to download your brew as a text file.
- Reduced download size and improved caching.
##### RKuerten :
- Bold and Italics hotkeys for Mac users (Cmd+B, Cmd+I)
### Friday, 25/1/2021 - v2.10.7 ### Friday, 25/1/2021 - v2.10.7
- Cover Page snippet now flips left-right page numbering. - Cover Page snippet now flips left-right page numbering.
- Added instructions for [installing on a FreeBSD Jail](https://github.com/naturalcrit/homebrewery/blob/master/README.FREEBSD.md). - Added instructions for [installing on a FreeBSD Jail](https://github.com/naturalcrit/homebrewery/blob/master/README.FREEBSD.md).
- Fix for box-shadows breaking across columns. <br>(Thanks @G-Ambatte for all of these!) - Fix for box-shadows breaking across columns. <br>(Thanks G-Ambatte for all of these!)
- Small user interface tweaks (Thanks @Ericsheid) - Small user interface tweaks (Thanks Ericsheid)
### Friday, 02/1/2021 - v2.10.6 ### Friday, 02/1/2021 - v2.10.6
- Fixed punctuation for usernames ending with 's' on the user page. (Thanks @AlexeySachkov) - Fixed punctuation for usernames ending with 's' on the user page. (Thanks AlexeySachkov)
- Fixed server crashes due to excessive long lines in brews - Fixed server crashes due to excessive long lines in brews
- Fixed "automated request" lockouts from Google - Fixed "automated request" lockouts from Google
@@ -30,12 +49,12 @@
- Fixed issue with users unable to create new brews - Fixed issue with users unable to create new brews
- Fixing brews being lost when loaded via back button - Fixing brews being lost when loaded via back button
```
```
### Wednesday, 07/10/2020 - v2.10.0 ### Wednesday, 07/10/2020 - v2.10.0
- Google Drive integration -- Sign in with your Google account to link it with your Homebrewery profile. A new button in the Edit page will let you transfer your file to your personal Google Drive storage, and Google will keep a backup of each version! No more lost work surprises! - Google Drive integration -- Sign in with your Google account to link it with your Homebrewery profile. A new button in the Edit page will let you transfer your file to your personal Google Drive storage, and Google will keep a backup of each version! No more lost work surprises!
```
```
### Friday, 28/08/2020 - v2.9.2 ### Friday, 28/08/2020 - v2.9.2
- Many dependency updates - Many dependency updates
- Finally fixed this changelog page to not run off the edge :P - Finally fixed this changelog page to not run off the edge :P
@@ -76,11 +95,11 @@
### Friday, 03/03/2017 - v2.7.3 ### Friday, 03/03/2017 - v2.7.3
- Increasing the range on the Partial Page Rendering for a quick-fix for it getting out of sync on long brews. - Increasing the range on the Partial Page Rendering for a quick-fix for it getting out of sync on long brews.
\page
### Saturday, 18/02/2017 - v2.7.2 ### Saturday, 18/02/2017 - v2.7.2
- Adding ability to delete a brew from the user page, incase the user creates a brew that makes the edit page unrender-able. (re:309) - Adding ability to delete a brew from the user page, incase the user creates a brew that makes the edit page unrender-able. (re:309)
\page
### Thursday, 19/01/2017 - v2.7.1 ### Thursday, 19/01/2017 - v2.7.1
- Fixed saving multiple authors and multiple systems on brew metadata (thanks u/PalaNolho re:282) - Fixed saving multiple authors and multiple systems on brew metadata (thanks u/PalaNolho re:282)
- Adding in line highlight for new pages - Adding in line highlight for new pages
@@ -116,15 +135,14 @@
- Added in a snippet for a split table - Added in a snippet for a split table
- Added an account nav item to new page - Added an account nav item to new page
```
```
### Sunday, 27/11/2016 - v2.5.1 ### Sunday, 27/11/2016 - v2.5.1
- Fixed the column rendering on the new user page. Really should have tested that better - Fixed the column rendering on the new user page. Really should have tested that better
- Added a hover tooltip to fully read the brew description - Added a hover tooltip to fully read the brew description
- Made the brew items take up only 25% allowing you to view more per row. - Made the brew items take up only 25% allowing you to view more per row.
```
```
### Wednesday, 23/11/2016 - v2.5.0 ### Wednesday, 23/11/2016 - v2.5.0
- Metadata can now be added to brews - Metadata can now be added to brews
- Added a metadata editor onto the edit and new pages - Added a metadata editor onto the edit and new pages
@@ -135,7 +153,6 @@
- Added a new user page to see others published brews, as well as all of your own brews. - Added a new user page to see others published brews, as well as all of your own brews.
- Added a new nav item for accessing your profile and logging in - Added a new nav item for accessing your profile and logging in
### Monday, 14/11/2016 ### Monday, 14/11/2016
- Updated snippet bar style - Updated snippet bar style
- You can now print from a new page without saving - You can now print from a new page without saving
@@ -160,6 +177,8 @@
- Fixed the noteblock overlapping into titles (thanks u/dsompura!) - Fixed the noteblock overlapping into titles (thanks u/dsompura!)
- Fixed a bad search route in the admin panel (thanks u/SnappyTom!) - Fixed a bad search route in the admin panel (thanks u/SnappyTom!)
\page
### Friday, 29/07/2016 - v2.2.7 ### Friday, 29/07/2016 - v2.2.7
- Adding in descriptive note blocks. (Thanks calculuschild!) - Adding in descriptive note blocks. (Thanks calculuschild!)
@@ -171,9 +190,6 @@
- Allows adding in hyperlinks to specific pages - Allows adding in hyperlinks to specific pages
- Even works after you print to pdf! - Even works after you print to pdf!
\page
### Tuesday, 07/06/2016 - v2.2.2 ### Tuesday, 07/06/2016 - v2.2.2
- Fixed bug with new markdown lexer and aprser not working on print page - Fixed bug with new markdown lexer and aprser not working on print page
@@ -197,10 +213,6 @@
- Updated the issue template for (hopefully) better reporting - Updated the issue template for (hopefully) better reporting
- Added suggestion to use chrome while PDF printing - Added suggestion to use chrome while PDF printing
```
```
### Wednesday, 25/05/2016 -v2.0.5 ### Wednesday, 25/05/2016 -v2.0.5
- The class table generators have the proper ability score improvement progression. - The class table generators have the proper ability score improvement progression.

View File

@@ -44,10 +44,11 @@ const Homebrew = createClass({
<Switch> <Switch>
<Route path='/edit/:id' component={(routeProps)=><EditPage id={routeProps.match.params.id} brew={this.props.brew} />}/> <Route path='/edit/:id' component={(routeProps)=><EditPage id={routeProps.match.params.id} brew={this.props.brew} />}/>
<Route path='/share/:id' component={(routeProps)=><SharePage id={routeProps.match.params.id} brew={this.props.brew} />}/> <Route path='/share/:id' component={(routeProps)=><SharePage id={routeProps.match.params.id} brew={this.props.brew} />}/>
<Route path='/new/:id' component={(routeProps)=><NewPage id={routeProps.match.params.id} brew={this.props.brew} />}/>
<Route path='/new' exact component={NewPage}/>
<Route path='/user/:username' component={(routeProps)=><UserPage username={routeProps.match.params.username} brews={this.props.brews} />}/> <Route path='/user/:username' component={(routeProps)=><UserPage username={routeProps.match.params.username} brews={this.props.brews} />}/>
<Route path='/print/:id' component={(routeProps)=><PrintPage brew={this.props.brew} query={queryString.parse(routeProps.location.search)} /> } /> <Route path='/print/:id' component={(routeProps)=><PrintPage brew={this.props.brew} query={queryString.parse(routeProps.location.search)} /> } />
<Route path='/print' exact component={(routeProps)=><PrintPage query={queryString.parse(routeProps.location.search)} /> } /> <Route path='/print' exact component={(routeProps)=><PrintPage query={queryString.parse(routeProps.location.search)} /> } />
<Route path='/new' exact component={NewPage}/>
<Route path='/changelog' exact component={()=><SharePage brew={{ title: 'Changelog', text: this.props.changelog }} />}/> <Route path='/changelog' exact component={()=><SharePage brew={{ title: 'Changelog', text: this.props.changelog }} />}/>
<Route path='/' component={()=><HomePage welcomeText={this.props.welcomeText}/>}/> <Route path='/' component={()=><HomePage welcomeText={this.props.welcomeText}/>}/>
</Switch> </Switch>

View File

@@ -0,0 +1,11 @@
const React = require('react');
const Nav = require('naturalcrit/nav/nav.jsx');
module.exports = function(props){
return <Nav.item
href='/new'
color='purple'
icon='fas fa-plus-square'>
new
</Nav.item>;
};

View File

@@ -1,5 +1,4 @@
const React = require('react'); const React = require('react');
const createClass = require('create-react-class');
const Nav = require('naturalcrit/nav/nav.jsx'); const Nav = require('naturalcrit/nav/nav.jsx');
module.exports = function(props){ module.exports = function(props){

View File

@@ -9,6 +9,7 @@ const { Meta } = require('vitreum/headtags');
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 NewBrew = require('../../navbar/newbrew.navitem.jsx');
const ReportIssue = require('../../navbar/issue.navitem.jsx'); const ReportIssue = require('../../navbar/issue.navitem.jsx');
const PrintLink = require('../../navbar/print.navitem.jsx'); const PrintLink = require('../../navbar/print.navitem.jsx');
const Account = require('../../navbar/account.navitem.jsx'); const Account = require('../../navbar/account.navitem.jsx');
@@ -372,6 +373,7 @@ const EditPage = createClass({
<Nav.section> <Nav.section>
{this.renderGoogleDriveIcon()} {this.renderGoogleDriveIcon()}
{this.renderSaveButton()} {this.renderSaveButton()}
<NewBrew />
<ReportIssue /> <ReportIssue />
<Nav.item newTab={true} href={`/share/${this.processShareId()}`} color='teal' icon='fas fa-share-alt'> <Nav.item newTab={true} href={`/share/${this.processShareId()}`} color='teal' icon='fas fa-share-alt'>
Share Share

View File

@@ -7,6 +7,7 @@ const { Meta } = require('vitreum/headtags');
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 NewBrewItem = require('../../navbar/newbrew.navitem.jsx');
const IssueNavItem = require('../../navbar/issue.navitem.jsx'); const IssueNavItem = require('../../navbar/issue.navitem.jsx');
const RecentNavItem = require('../../navbar/recent.navitem.jsx').both; const RecentNavItem = require('../../navbar/recent.navitem.jsx').both;
const AccountNavItem = require('../../navbar/account.navitem.jsx'); const AccountNavItem = require('../../navbar/account.navitem.jsx');
@@ -59,6 +60,7 @@ const HomePage = createClass({
renderNavbar : function(){ renderNavbar : function(){
return <Navbar ver={this.props.ver}> return <Navbar ver={this.props.ver}>
<Nav.section> <Nav.section>
<NewBrewItem />
<IssueNavItem /> <IssueNavItem />
<Nav.item newTab={true} href='/changelog' color='purple' icon='far fa-file-alt'> <Nav.item newTab={true} href='/changelog' color='purple' icon='far fa-file-alt'>
Changelog Changelog

View File

@@ -20,10 +20,30 @@ const BrewRenderer = require('../../brewRenderer/brewRenderer.jsx');
const KEY = 'homebrewery-new'; const KEY = 'homebrewery-new';
const NewPage = createClass({ const NewPage = createClass({
getInitialState : function() { getDefaultProps : function() {
return { return {
brew : { brew : {
text : '', text : '',
shareId : null,
editId : null,
createdAt : null,
updatedAt : null,
gDrive : false,
title : '',
description : '',
tags : '',
published : false,
authors : [],
systems : []
}
};
},
getInitialState : function() {
return {
brew : {
text : this.props.brew.text,
gDrive : false, gDrive : false,
title : '', title : '',
description : '', description : '',
@@ -41,7 +61,7 @@ const NewPage = createClass({
componentDidMount : function() { componentDidMount : function() {
const storage = localStorage.getItem(KEY); const storage = localStorage.getItem(KEY);
if(storage){ if(!this.props.brew.text && storage){
this.setState({ this.setState({
brew : { text: storage } brew : { text: storage }
}); });

View File

@@ -63,6 +63,9 @@ const SharePage = createClass({
<Nav.item href={`/source/${this.processShareId()}`} color='teal' icon='fas fa-code'> <Nav.item href={`/source/${this.processShareId()}`} color='teal' icon='fas fa-code'>
source source
</Nav.item> </Nav.item>
<Nav.item href={`/download/${this.processShareId()}`} color='red' icon='fas fa-download'>
download
</Nav.item>
<RecentNavItem brew={this.props.brew} storageKey='view' /> <RecentNavItem brew={this.props.brew} storageKey='view' />
<Account /> <Account />
</Nav.section> </Nav.section>

View File

@@ -78,6 +78,19 @@ const BrewItem = createClass({
</a>; </a>;
}, },
renderDownloadLink : function(){
if(!this.props.brew.shareId) return;
let shareLink = this.props.brew.shareId;
if(this.props.brew.googleId) {
shareLink = this.props.brew.googleId + shareLink;
}
return <a href={`/download/${shareLink}`}>
<i className='fas fa-download' />
</a>;
},
renderGoogleDriveIcon : function(){ renderGoogleDriveIcon : function(){
if(!this.props.brew.gDrive) return; if(!this.props.brew.gDrive) return;
@@ -109,6 +122,7 @@ const BrewItem = createClass({
<div className='links'> <div className='links'>
{this.renderShareLink()} {this.renderShareLink()}
{this.renderEditLink()} {this.renderEditLink()}
{this.renderDownloadLink()}
{this.renderDeleteBrewLink()} {this.renderDeleteBrewLink()}
</div> </div>
</div>; </div>;

View File

@@ -7,7 +7,7 @@
box-sizing : border-box; box-sizing : border-box;
overflow : hidden; overflow : hidden;
width : 48%; width : 48%;
min-height : 80px; min-height : 105px;
margin-right : 15px; margin-right : 15px;
margin-bottom : 15px; margin-bottom : 15px;
padding : 5px 15px 5px 8px; padding : 5px 15px 5px 8px;

View File

@@ -9,6 +9,7 @@ const Navbar = require('../../navbar/navbar.jsx');
const RecentNavItem = require('../../navbar/recent.navitem.jsx').both; const RecentNavItem = require('../../navbar/recent.navitem.jsx').both;
const Account = require('../../navbar/account.navitem.jsx'); const Account = require('../../navbar/account.navitem.jsx');
const NewBrew = require('../../navbar/newbrew.navitem.jsx');
const BrewItem = require('./brewItem/brewItem.jsx'); const BrewItem = require('./brewItem/brewItem.jsx');
// const brew = { // const brew = {
@@ -54,6 +55,7 @@ const UserPage = createClass({
return <div className='userPage page'> return <div className='userPage page'>
<Navbar> <Navbar>
<Nav.section> <Nav.section>
<NewBrew />
<RecentNavItem /> <RecentNavItem />
<Account /> <Account />
</Nav.section> </Nav.section>

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,73 @@
/* Main Font, serif */
@font-face {
font-family: BookInsanityRemake;
src: url('../fonts/v3/Bookinsanity.woff2');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: BookInsanityRemake;
src: url('../fonts/v3/Bookinsanity Bold.woff2');
font-weight: bold;
font-style: normal;
}
@font-face {
font-family: BookInsanityRemake;
src: url('../fonts/v3/Bookinsanity Italic.woff2');
font-weight: normal;
font-style: italic;
}
@font-face {
font-family: BookInsanityRemake;
src: url('../fonts/v3/Bookinsanity Bold Italic.woff2');
font-weight: bold;
font-style: italic;
}
/* Notes and Tables, sans-serif */
@font-face {
font-family: ScalySansRemake;
src: url('../fonts/v3/Scaly Sans.woff2');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: ScalySansRemake;
src: url('../fonts/v3/Scaly Sans Bold.woff2');
font-weight: bold;
font-style: normal;
}
@font-face {
font-family: ScalySansRemake;
src: url('../fonts/v3/Scaly Sans Italic.woff2');
font-weight: normal;
font-style: italic;
}
@font-face {
font-family: ScalySansRemake;
src: url('../fonts/v3/Scaly Sans Bold Italic.woff2');
font-weight: bold;
font-style: italic;
}
@font-face {
font-family: ScalySansSmallCapsRemake;
src: url('../fonts/v3/Scaly Sans Caps.woff2');
font-weight: normal;
font-style: normal;
}
/* Headers */
@font-face {
font-family: MrEavesRemake;
src: url('../fonts/v3/Mr Eaves Small Caps.woff2');
font-weight: normal;
font-style: normal;
}
/* Fancy Drop Cap */
@font-face {
font-family: SolberaImitationRemake; //Tweaked v3 version
src: url('../fonts/v3/Solbera Imitation Tweak.woff2');
font-weight: normal;
font-style: normal;
}

View File

@@ -0,0 +1,55 @@
/* Main Font, serif */
@font-face {
font-family: BookSanity;
src: url('../fonts/legacy/Bookinsanity.woff2');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: BookSanity;
src: url('../fonts/legacy/Bookinsanity Bold.woff2');
font-weight: bold;
font-style: normal;
}
@font-face {
font-family: BookSanity;
src: url('../fonts/legacy/Bookinsanity Italic.woff2');
font-weight: normal;
font-style: italic;
}
@font-face {
font-family: BookSanity;
src: url('../fonts/legacy/Bookinsanity Bold Italic.woff2');
font-weight: bold;
font-style: italic;
}
/* Notes and Tables, sans-serif */
@font-face {
font-family: ScalySans;
src: url('../fonts/legacy/Scaly Sans.woff2');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: ScalySansSmallCaps;
src: url('../fonts/legacy/Scaly Sans Caps.woff2');
font-weight: normal;
font-style: normal;
}
/* Headers */
@font-face {
font-family: MrJeeves;
src: url('../fonts/legacy/Mr Eaves Small Caps.woff2');
font-weight: normal;
font-style: normal;
}
/* Fancy Drop Cap */
@font-face {
font-family: Solberry;
src: url('../fonts/legacy/Solbera Imitation.woff2');
font-weight: normal;
font-style: normal;
}

View File

@@ -1,4 +1,4 @@
@import (less) './client/homebrew/phbStyle/phb.fonts.css'; @import (less) './client/homebrew/phbStyle/phb.fonts.less';
@import (less) './client/homebrew/phbStyle/phb.assets.less'; @import (less) './client/homebrew/phbStyle/phb.assets.less';
//Colors //Colors
@@ -16,7 +16,7 @@ body {
-webkit-print-color-adjust : exact; -webkit-print-color-adjust : exact;
} }
.useSansSerif(){ .useSansSerif(){
font-family : ScalySans; font-family : ScalySansRemake;
font-size : 10pt; font-size : 10pt;
em{ em{
font-style : italic; font-style : italic;
@@ -50,7 +50,7 @@ body {
padding : 1.0cm 1.7cm 1.5cm; padding : 1.0cm 1.7cm 1.5cm;
background-color : @background; background-color : @background;
background-image : @backgroundImage; background-image : @backgroundImage;
font-family : BookSanity; font-family : BookInsanityRemake;
font-size : 0.317cm; font-size : 0.317cm;
text-rendering : optimizeLegibility; text-rendering : optimizeLegibility;
page-break-before : always; page-break-before : always;
@@ -110,7 +110,7 @@ body {
h1,h2,h3,h4{ h1,h2,h3,h4{
margin-top : 0.2em; margin-top : 0.2em;
margin-bottom : 0.2em; margin-bottom : 0.2em;
font-family : MrJeeves; font-family : MrEavesRemake;
font-weight : 800; font-weight : 800;
color : @headerText; color : @headerText;
} }
@@ -121,13 +121,15 @@ body {
-moz-column-span : all; -moz-column-span : all;
&+p::first-letter{ &+p::first-letter{
float : left; float : left;
font-family : Solberry; font-family : SolberaImitationRemake;
line-height : 0.8em; line-height : 0.8em;
font-size: 3.1cm; font-size: 3.5cm;
padding-top: 4px; padding-left: 40px;
padding-bottom: 4px; margin-left: -40px;
margin-top: -6px; padding-top:10px;
margin-left: -6px; margin-top:-8px;
padding-bottom:10px;
margin-bottom:-20px;
background-image: linear-gradient(-45deg, #322814, #998250, #322814); background-image: linear-gradient(-45deg, #322814, #998250, #322814);
background-clip: text; background-clip: text;
-webkit-background-clip: text; -webkit-background-clip: text;
@@ -151,7 +153,7 @@ body {
} }
h5{ h5{
margin-bottom : 0.2em; margin-bottom : 0.2em;
font-family : ScalySansSmallCaps; font-family : ScalySansSmallCapsRemake;
font-size : 0.423cm; font-size : 0.423cm;
font-weight : 900; font-weight : 900;
} }
@@ -226,7 +228,7 @@ body {
} }
} }
h3{ h3{
font-family : ScalySans; font-family : ScalySansRemake;
font-weight : 400; font-weight : 400;
border-bottom : 1px solid @headerText; border-bottom : 1px solid @headerText;
} }
@@ -429,7 +431,7 @@ body {
display : block-inline; display : block-inline;
margin-bottom : 1em; margin-bottom : 1em;
background-color : #faf7ea; background-color : #faf7ea;
font-family : ScalySans; font-family : ScalySansRemake;
border-style : solid; border-style : solid;
border-width : 7px; border-width : 7px;
border-image : @descriptiveBoxImage 12 stretch; border-image : @descriptiveBoxImage 12 stretch;
@@ -444,11 +446,11 @@ body {
padding-top : .8em; padding-top : .8em;
} }
em { em {
font-family : ScalySans; font-family : ScalySansRemake;
font-style : italic; font-style : italic;
} }
strong { strong {
font-family : ScalySans; font-family : ScalySansRemake;
font-weight : 800; font-weight : 800;
letter-spacing : -0.02em; letter-spacing : -0.02em;
} }

View File

@@ -1,4 +1,4 @@
@import (less) './client/homebrew/phbStyle/phb.fonts.css'; @import (less) './client/homebrew/phbStyle/phb.fontsLegacy.less';
@import (less) './client/homebrew/phbStyle/phb.assets.less'; @import (less) './client/homebrew/phbStyle/phb.assets.less';
@import (less) './client/homebrew/phbStyle/phb.depricated.less'; @import (less) './client/homebrew/phbStyle/phb.depricated.less';
//Colors //Colors

2479
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{ {
"name": "homebrewery", "name": "homebrewery",
"description": "Create authentic looking D&D homebrews using only markdown", "description": "Create authentic looking D&D homebrews using only markdown",
"version": "2.10.7", "version": "2.11.0",
"engines": { "engines": {
"node": "14.15.x" "node": "14.15.x"
}, },
@@ -40,8 +40,8 @@
] ]
}, },
"dependencies": { "dependencies": {
"@babel/core": "^7.13.1", "@babel/core": "^7.13.10",
"@babel/preset-env": "^7.13.5", "@babel/preset-env": "^7.13.10",
"@babel/preset-react": "^7.12.13", "@babel/preset-react": "^7.12.13",
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"classnames": "^2.2.6", "classnames": "^2.2.6",
@@ -51,27 +51,28 @@
"express": "^4.17.1", "express": "^4.17.1",
"express-static-gzip": "2.1.1", "express-static-gzip": "2.1.1",
"fs-extra": "9.1.0", "fs-extra": "9.1.0",
"googleapis": "67.1.0", "googleapis": "67.1.1",
"jwt-simple": "^0.5.6", "jwt-simple": "^0.5.6",
"less": "^3.13.1", "less": "^3.13.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"moment": "^2.29.1", "moment": "^2.29.1",
"mongoose": "^5.11.18", "mongoose": "^5.12.0",
"nanoid": "3.1.20", "nanoid": "3.1.21",
"markedLegacy": "npm:marked@^0.3.19", "markedLegacy": "npm:marked@^0.3.19",
"marked": "2.0.0", "marked": "2.0.1",
"nconf": "^0.11.2", "nconf": "^0.11.2",
"prop-types": "15.7.2", "prop-types": "15.7.2",
"query-string": "6.14.0", "query-string": "6.14.1",
"react": "^16.14.0", "react": "^16.14.0",
"react-dom": "^16.14.0", "react-dom": "^16.14.0",
"react-frame-component": "4.1.3", "react-frame-component": "4.1.3",
"react-router-dom": "5.2.0", "react-router-dom": "5.2.0",
"sanitize-filename": "1.6.3",
"superagent": "^6.1.0", "superagent": "^6.1.0",
"vitreum": "github:calculuschild/vitreum#21a8e1c9421f1d3a3b474c12f480feb2fbd28c5b" "vitreum": "github:calculuschild/vitreum#21a8e1c9421f1d3a3b474c12f480feb2fbd28c5b"
}, },
"devDependencies": { "devDependencies": {
"eslint": "^7.20.0", "eslint": "^7.21.0",
"eslint-plugin-react": "^7.22.0", "eslint-plugin-react": "^7.22.0",
"pico-check": "^2.0.3" "pico-check": "^2.0.3"
} }

View File

@@ -19,6 +19,7 @@ const build = async ({ bundle, render, ssr })=>{
await fs.outputFile('./build/homebrew/bundle.css', css); await fs.outputFile('./build/homebrew/bundle.css', css);
await fs.outputFile('./build/homebrew/bundle.js', bundle); await fs.outputFile('./build/homebrew/bundle.js', bundle);
await fs.outputFile('./build/homebrew/ssr.js', ssr); await fs.outputFile('./build/homebrew/ssr.js', ssr);
await fs.copy('./client/homebrew/phbStyle/fonts', './build/fonts');
//compress files in production //compress files in production
if(!isDev){ if(!isDev){

View File

@@ -1,3 +1,4 @@
/*eslint max-lines: ["warn", {"max": 300, "skipBlankLines": true, "skipComments": true}]*/
const _ = require('lodash'); const _ = require('lodash');
const jwt = require('jwt-simple'); const jwt = require('jwt-simple');
const express = require('express'); const express = require('express');
@@ -6,6 +7,7 @@ const app = express();
const homebrewApi = require('./server/homebrew.api.js'); const homebrewApi = require('./server/homebrew.api.js');
const GoogleActions = require('./server/googleActions.js'); const GoogleActions = require('./server/googleActions.js');
const serveCompressedStaticAssets = require('./server/static-assets.mv.js'); const serveCompressedStaticAssets = require('./server/static-assets.mv.js');
const sanitizeFilename = require('sanitize-filename');
app.use('/', serveCompressedStaticAssets(`${__dirname}/build`)); app.use('/', serveCompressedStaticAssets(`${__dirname}/build`));
@@ -63,6 +65,7 @@ app.get('/robots.txt', (req, res)=>{
return res.sendFile(`${__dirname}/robots.txt`); return res.sendFile(`${__dirname}/robots.txt`);
}); });
//Source page //Source page
app.get('/source/:id', (req, res)=>{ app.get('/source/:id', (req, res)=>{
if(req.params.id.length > 12) { if(req.params.id.length > 12) {
@@ -70,8 +73,13 @@ app.get('/source/:id', (req, res)=>{
const shareId = req.params.id.slice(-12); const shareId = req.params.id.slice(-12);
GoogleActions.readFileMetadata(config.get('google_api_key'), googleId, shareId, 'share') GoogleActions.readFileMetadata(config.get('google_api_key'), googleId, shareId, 'share')
.then((brew)=>{ .then((brew)=>{
const text = brew.text.replaceAll('<', '&lt;').replaceAll('>', '&gt;'); const replaceStrings = { '&': '&amp;', '<': '&lt;', '>': '&gt;' };
return res.send(`<code><pre style="white-space: pre-wrap;">${text}</pre></code>`); let text = brew.text;
for (const replaceStr in replaceStrings) {
text = text.replaceAll(replaceStr, replaceStrings[replaceStr]);
}
text = `<code><pre style="white-space: pre-wrap;">${text}</pre></code>`;
res.status(200).send(text);
}) })
.catch((err)=>{ .catch((err)=>{
console.log(err); console.log(err);
@@ -80,8 +88,54 @@ app.get('/source/:id', (req, res)=>{
} else { } else {
HomebrewModel.get({ shareId: req.params.id }) HomebrewModel.get({ shareId: req.params.id })
.then((brew)=>{ .then((brew)=>{
const text = brew.text.replaceAll('<', '&lt;').replaceAll('>', '&gt;'); const replaceStrings = { '&': '&amp;', '<': '&lt;', '>': '&gt;' };
return res.send(`<code><pre style="white-space: pre-wrap;">${text}</pre></code>`); let text = brew.text;
for (const replaceStr in replaceStrings) {
text = text.replaceAll(replaceStr, replaceStrings[replaceStr]);
}
text = `<code><pre style="white-space: pre-wrap;">${text}</pre></code>`;
res.status(200).send(text);
})
.catch((err)=>{
console.log(err);
return res.status(404).send('Could not find Homebrew with that id');
});
}
});
//Download brew source page
app.get('/download/:id', (req, res)=>{
const prefix = 'HB - ';
if(req.params.id.length > 12) {
const googleId = req.params.id.slice(0, -12);
const shareId = req.params.id.slice(-12);
GoogleActions.readFileMetadata(config.get('google_api_key'), googleId, shareId, 'share')
.then((brew)=>{
let fileName = sanitizeFilename(`${prefix}${brew.title}`).replaceAll(' ', '');
if(!fileName || !fileName.length) { fileName = `${prefix}-Untitled-Brew`; };
res.set({
'Cache-Control' : 'no-cache',
'Content-Type' : 'text/plain',
'Content-Disposition' : `attachment; filename="${fileName}.txt"`
});
res.status(200).send(brew.text);
})
.catch((err)=>{
console.log(err);
return res.status(400).send('Can\'t get brew from Google');
});
} else {
HomebrewModel.get({ shareId: req.params.id })
.then((brew)=>{
let fileName = sanitizeFilename(`${prefix}${brew.title}`).replaceAll(' ', '');
if(!fileName || !fileName.length) { fileName = `${prefix}-Untitled-Brew`; };
res.set({
'Cache-Control' : 'no-cache',
'Content-Type' : 'text/plain',
'Content-Disposition' : `attachment; filename="${fileName}.txt"`
});
res.status(200).send(brew.text);
}) })
.catch((err)=>{ .catch((err)=>{
console.log(err); console.log(err);
@@ -143,6 +197,33 @@ app.get('/edit/:id', (req, res, next)=>{
} }
}); });
//New Page
app.get('/new/:id', (req, res, next)=>{
if(req.params.id.length > 12) {
const googleId = req.params.id.slice(0, -12);
const shareId = req.params.id.slice(-12);
GoogleActions.readFileMetadata(config.get('google_api_key'), googleId, shareId, 'share')
.then((brew)=>{
req.brew = brew; //TODO Need to sanitize later
return next();
})
.catch((err)=>{
console.log(err);
return res.status(400).send('Can\'t get brew from Google');
});
} else {
HomebrewModel.get({ shareId: req.params.id })
.then((brew)=>{
req.brew = brew;
return next();
})
.catch((err)=>{
console.log(err);
return res.status(400).send(`Can't get that`);
});
}
});
//Share Page //Share Page
app.get('/share/:id', (req, res, next)=>{ app.get('/share/:id', (req, res, next)=>{
if(req.params.id.length > 12) { if(req.params.id.length > 12) {

View File

@@ -259,8 +259,12 @@ GoogleActions = {
throw ('Share ID does not match'); throw ('Share ID does not match');
} }
//Access actual file with service account. Just api key is causing "automated query" errors. //Access file using service account. Using API key only causes "automated query" lockouts after a while.
const keys = JSON.parse(config.get('service_account'));
const keys = typeof(config.get('service_account')) == 'string' ?
JSON.parse(config.get('service_account')) :
config.get('service_account');
const serviceAuth = google.auth.fromJSON(keys); const serviceAuth = google.auth.fromJSON(keys);
serviceAuth.scopes = ['https://www.googleapis.com/auth/drive']; serviceAuth.scopes = ['https://www.googleapis.com/auth/drive'];

View File

@@ -1,4 +1,3 @@
//@import (less) 'naturalcrit/styles/style.fonts.css';
nav{ nav{
background-color : #333; background-color : #333;
.navContent{ .navContent{