0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2026-01-27 13:53:09 +00:00

Merge pull request #1342 from naturalcrit/master

v2.11.2
This commit is contained in:
Trevor Buckner
2021-05-02 22:15:43 -04:00
committed by GitHub
32 changed files with 1481 additions and 1780 deletions

69
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,69 @@
version: 2
updates:
- package-ecosystem: npm
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 99
ignore:
- dependency-name: eslint
versions:
- 7.19.0
- 7.22.0
- 7.23.0
- 7.24.0
- dependency-name: "@babel/core"
versions:
- 7.12.13
- 7.12.16
- 7.12.17
- 7.13.13
- 7.13.14
- 7.13.15
- dependency-name: googleapis
versions:
- 68.0.0
- 70.0.0
- 71.0.0
- dependency-name: "@babel/preset-env"
versions:
- 7.12.13
- 7.12.16
- 7.12.17
- 7.13.0
- 7.13.12
- 7.13.8
- dependency-name: mongoose
versions:
- 5.11.14
- 5.11.15
- 5.11.16
- 5.11.17
- 5.11.18
- 5.11.19
- 5.12.1
- 5.12.2
- 5.12.3
- dependency-name: eslint-plugin-react
versions:
- 7.23.0
- 7.23.1
- dependency-name: query-string
versions:
- 7.0.0
- dependency-name: nanoid
versions:
- 3.1.22
- dependency-name: "@babel/preset-react"
versions:
- 7.13.13
- dependency-name: codemirror
versions:
- 5.59.3
- 5.60.0
- dependency-name: classnames
versions:
- 2.3.0
- dependency-name: marked
versions:
- 1.2.8

View File

@@ -6,6 +6,11 @@ h5 {
# changelog # changelog
### Saturday, 02/5/2021 - v2.11.2
- Fix for edge case where brews could accidentally transfer from Google Drive back to Homebrewery.
- Move cursor to end of snippet after insertion
### Saturday, 20/3/2021 - v2.11.1 ### Saturday, 20/3/2021 - v2.11.1
- Warning when opening brew in your Google Drive trash - Warning when opening brew in your Google Drive trash
@@ -52,10 +57,6 @@ h5 {
### Monday, 19/10/2020 - v2.10.2 ### Monday, 19/10/2020 - v2.10.2
- Fixed issue with "recent" item links not updating when transferring between Google Drive. - Fixed issue with "recent" item links not updating when transferring between Google Drive.
```
```
### Monday, 12/10/2020 - v2.10.1 ### Monday, 12/10/2020 - v2.10.1
- 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
@@ -73,6 +74,13 @@ h5 {
### Wednesday, 20/05/2020 - v2.9.0 ### Wednesday, 20/05/2020 - v2.9.0
- Major refactoring of site backend to work with updated dependencies for security (should be invisible to users) - Major refactoring of site backend to work with updated dependencies for security (should be invisible to users)
\page
### Wednesday, 11/03/2020 - v2.8.2 ### Wednesday, 11/03/2020 - v2.8.2
- Fixed delete button removing everyone's copy for brews with multiple authors - Fixed delete button removing everyone's copy for brews with multiple authors
- Compressed homebrew text in database - Compressed homebrew text in database
@@ -100,9 +108,6 @@ h5 {
### Saturday, 22/04/2017 - v2.7.4 ### Saturday, 22/04/2017 - v2.7.4
- Give ability to hide the render warning notification - Give ability to hide the render warning notification
\page
### 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.
@@ -144,9 +149,6 @@ h5 {
- 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
@@ -167,6 +169,8 @@ h5 {
- You can now print from a new page without saving - You can now print from a new page without saving
- Added the ability to use ctrl+p and ctrl+s to print and save respectively. - Added the ability to use ctrl+p and ctrl+s to print and save respectively.
\page
### Monday, 07/11/2016 ### Monday, 07/11/2016
- Added final touches to the html validator and updating the rest of the branch - Added final touches to the html validator and updating the rest of the branch
- If anyone finds issues with the new HTML validator, please let me know. I hope this will bring a more consistent feel to Homebrewery rendering. - If anyone finds issues with the new HTML validator, please let me know. I hope this will bring a more consistent feel to Homebrewery rendering.
@@ -186,8 +190,6 @@ h5 {
- 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!)

View File

@@ -64,7 +64,7 @@ const Editor = createClass({
lines[this.cursorPosition.line] = splice(lines[this.cursorPosition.line], this.cursorPosition.ch, injectText); lines[this.cursorPosition.line] = splice(lines[this.cursorPosition.line], this.cursorPosition.ch, injectText);
this.handleTextChange(lines.join('\n')); this.handleTextChange(lines.join('\n'));
this.refs.codeEditor.setCursorPosition(this.cursorPosition.line, this.cursorPosition.ch + injectText.length); this.refs.codeEditor.setCursorPosition(this.cursorPosition.line + injectText.split('\n').length, this.cursorPosition.ch + injectText.length);
}, },
handgleToggle : function(){ handgleToggle : function(){
this.setState({ this.setState({

View File

@@ -88,7 +88,7 @@ module.exports = {
`- **Components:** ${components}`, `- **Components:** ${components}`,
`- **Duration:** ${_.sample(['Until dispelled', '1 round', 'Instantaneous', 'Concentration, up to 10 minutes', '1 hour'])}`, `- **Duration:** ${_.sample(['Until dispelled', '1 round', 'Instantaneous', 'Concentration, up to 10 minutes', '1 hour'])}`,
'', '',
'A flame, equivalent in brightness to a torch, springs from from an object that you touch. ', 'A flame, equivalent in brightness to a torch, springs from an object that you touch. ',
'The effect look like a regular flame, but it creates no heat and doesn\'t use oxygen. ', 'The effect look like a regular flame, but it creates no heat and doesn\'t use oxygen. ',
'A *continual flame* can be covered or hidden but not smothered or quenched.', 'A *continual flame* can be covered or hidden but not smothered or quenched.',
'\n\n\n' '\n\n\n'

View File

@@ -1,4 +1,5 @@
const _ = require('lodash'); const _ = require('lodash');
const dedent = require('dedent-tabs').default;
const genList = function(list, max){ const genList = function(list, max){
return _.sampleSize(list, _.random(0, max)).join(', ') || 'None'; return _.sampleSize(list, _.random(0, max)).join(', ') || 'None';
@@ -86,7 +87,7 @@ const getAlignment = function(){
}; };
const getStats = function(){ const getStats = function(){
return `>|${_.times(6, function(){ return `|${_.times(6, function(){
const num = _.random(1, 20); const num = _.random(1, 20);
const mod = Math.ceil(num/2 - 5); const mod = Math.ceil(num/2 - 5);
return `${num} (${mod >= 0 ? `+${mod}` : mod})`; return `${num} (${mod >= 0 ? `+${mod}` : mod})`;
@@ -95,12 +96,12 @@ const getStats = function(){
const genAbilities = function(){ const genAbilities = function(){
return _.sample([ return _.sample([
'> ***Pack Tactics.*** These guys work together. Like super well, you don\'t even know.', '***Pack Tactics.*** These guys work together like peanut butter and jelly.',
'> ***Fowl Appearance.*** While the creature remains motionless, it is indistinguishable from a normal chicken.', '***Fowl Appearance.*** While the creature remains motionless, it is indistinguishable from a normal chicken.',
'> ***Onion Stench.*** Any creatures within 5 feet of this thing develops an irrational craving for onion rings.', '***Onion Stench.*** Any creatures within 5 feet of this thing develops an irrational craving for onion rings.',
'> ***Enormous Nose.*** This creature gains advantage on any check involving putting things in its nose.', '***Enormous Nose.*** This creature gains advantage on any check involving putting things in its nose.',
'> ***Sassiness.*** When questioned, this creature will talk back instead of answering.', '***Sassiness.*** When questioned, this creature will talk back instead of answering.',
'> ***Big Jerk.*** Thinks he is just *waaaay* better than you.', '***Big Jerk.*** Whenever this creature makes an attack, it starts telling you how much cooler it is than you.',
]); ]);
}; };
@@ -133,68 +134,37 @@ const genAction = function(){
'Turnbuckle Roll' 'Turnbuckle Roll'
]); ]);
return `> ***${name}.*** *Melee Weapon Attack:* +4 to hit, reach 5ft., one target. *Hit* 5 (1d6 + 2) `; return `***${name}.*** *Melee Weapon Attack:* +4 to hit, reach 5ft., one target. *Hit* 5 (1d6 + 2) `;
}; };
module.exports = { module.exports = {
full : function(){ monster : function(classes, genLines){
return `${[ return dedent`
'___', {{${classes}
'___', ## ${getMonsterName()}
`> ## ${getMonsterName()}`, *${getType()}, ${getAlignment()}*
`>*${getType()}, ${getAlignment()}*`, ___
'> ___', : **Armor Class** : ${_.random(10, 20)} (chain mail, shield)
`> - **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(), ___
'>___', : **Condition Immunities** : ${genList(['groggy', 'swagged', 'weak-kneed', 'buzzed', 'groovy', 'melancholy', 'drunk'], 3)}
`> - **Condition Immunities** ${genList(['groggy', 'swagged', 'weak-kneed', 'buzzed', 'groovy', 'melancholy', 'drunk'], 3)}`, : **Senses** : darkvision 60 ft., passive Perception ${_.random(3, 20)}
`> - **Senses** passive Perception ${_.random(3, 20)}`, : **Languages** : ${genList(['Common', 'Pottymouth', 'Gibberish', 'Latin', 'Jive'], 2)}
`> - **Languages** ${genList(['Common', 'Pottymouth', 'Gibberish', 'Latin', 'Jive'], 2)}`, : **Challenge** : ${_.random(0, 15)} (${_.random(10, 10000)} XP)
`> - **Challenge** ${_.random(0, 15)} (${_.random(10, 10000)} XP)`, ___
'> ___', :
_.times(_.random(3, 6), function(){ ${_.times(_.random(genLines, genLines + 2), function(){return genAbilities();}).join('\n\t\t\t\n\t\t\t')}
return genAbilities(); :
}).join('\n>\n'), ### Actions
'> ### Actions', ${_.times(_.random(genLines, genLines + 2), function(){return genAction();}).join('\n\t\t\t\n\t\t\t')}
_.times(_.random(4, 6), function(){ }}
return genAction(); \n`;
}).join('\n>\n'),
].join('\n')}\n\n\n`;
},
half : function(){
return `${[
'___',
`> ## ${getMonsterName()}`,
`>*${getType()}, ${getAlignment()}*`,
'> ___',
`> - **Armor Class** ${_.random(10, 20)}`,
`> - **Hit Points** ${_.random(1, 150)}(1d4 + 5)`,
`> - **Speed** ${_.random(0, 50)}ft.`,
'>___',
'>|STR|DEX|CON|INT|WIS|CHA|',
'>|:---:|:---:|:---:|:---:|:---:|:---:|',
getStats(),
'>___',
`> - **Condition Immunities** ${genList(['groggy', 'swagged', 'weak-kneed', 'buzzed', 'groovy', 'melancholy', 'drunk'], 3)}`,
`> - **Senses** passive Perception ${_.random(3, 20)}`,
`> - **Languages** ${genList(['Common', 'Pottymouth', 'Gibberish', 'Latin', 'Jive'], 2)}`,
`> - **Challenge** ${_.random(0, 15)} (${_.random(10, 10000)} XP)`,
'> ___',
_.times(_.random(2, 3), function(){
return genAbilities();
}).join('\n>\n'),
'> ### Actions',
_.times(_.random(1, 2), function(){
return genAction();
}).join('\n>\n'),
].join('\n')}\n\n\n`;
} }
}; };

View File

@@ -6,6 +6,7 @@ const MonsterBlockGen = require('./monsterblock.gen.js');
const ClassFeatureGen = require('./classfeature.gen.js'); const ClassFeatureGen = require('./classfeature.gen.js');
const CoverPageGen = require('./coverpage.gen.js'); const CoverPageGen = require('./coverpage.gen.js');
const TableOfContentsGen = require('./tableOfContents.gen.js'); const TableOfContentsGen = require('./tableOfContents.gen.js');
const dedent = require('dedent-tabs').default;
module.exports = [ module.exports = [
@@ -151,15 +152,20 @@ module.exports = [
].join('\n'); ].join('\n');
}, },
}, },
{
name : 'Monster Stat Block (unframed)',
icon : 'fas fa-paw',
gen : MonsterBlockGen.monster('monster', 2),
},
{ {
name : 'Monster Stat Block', name : 'Monster Stat Block',
icon : 'fas fa-spider', icon : 'fas fa-spider',
gen : MonsterBlockGen.half, gen : MonsterBlockGen.monster('monster,frame', 2),
}, },
{ {
name : 'Wide Monster Stat Block', name : 'Wide Monster Stat Block',
icon : 'fas fa-dragon', icon : 'fas fa-dragon',
gen : MonsterBlockGen.full, gen : MonsterBlockGen.monster('monster,frame,wide', 4),
}, },
{ {
name : 'Cover Page', name : 'Cover Page',
@@ -196,63 +202,61 @@ module.exports = [
name : 'Table', name : 'Table',
icon : 'fas fa-th-list', icon : 'fas fa-th-list',
gen : function(){ gen : function(){
return [ return dedent`
'##### Cookie Tastiness', ##### Character Advancement
'| Tastiness | Cookie Type |', | Experience Points | Level | Proficiency Bonus |
'|:----:|:-------------|', |:------------------|:-----:|:-----------------:|
'| -5 | Raisin |', | 0 | 1 | +2 |
'| 8th | Chocolate Chip |', | 300 | 2 | +2 |
'| 11th | 2 or lower |', | 900 | 3 | +2 |
'| 14th | 3 or lower |', | 2,700 | 4 | +2 |
'| 17th | 4 or lower |\n\n', | 6,500 | 5 | +3 |
].join('\n'); | 14,000 | 6 | +3 |
}, \n`;
}
}, },
{ {
name : 'Wide Table', name : 'Wide Table',
icon : 'fas fa-list', icon : 'fas fa-list',
gen : function(){ gen : function(){
return [ return dedent`
'<div class=\'wide\'>', {{wide
'##### Cookie Tastiness', ##### Weapons
'| Tastiness | Cookie Type |', | Name | Cost | Damage | Weight | Properties |
'|:----:|:-------------|', |:------------------------|:-----:|:----------------|--------:|:-----------|
'| -5 | Raisin |', | *Simple Melee Weapons* | | | | |
'| 8th | Chocolate Chip |', | &emsp; Club | 1 sp | 1d4 bludgeoning | 2 lb. | Light |
'| 11th | 2 or lower |', | &emsp; Dagger | 2 gp | 1d4 piercing | 1 lb. | Finesse |
'| 14th | 3 or lower |', | &emsp; Spear | 1 gp | 1d6 piercing | 3 lb. | Thrown |
'| 17th | 4 or lower |', | *Simple Ranged Weapons* | | | | |
'</div>\n\n' | &emsp; Dart | 5 cp | 1d4 piercig | 1/4 lb. | Finesse |
].join('\n'); | &emsp; Shortbow | 25 gp | 1d6 piercing | 2 lb. | Ammunition |
}, | &emsp; Sling | 1 sp | 1d4 bludgeoning | &mdash; | Ammunition |
}}
\n`;
}
}, },
{ {
name : 'Split Table', name : 'Split Table',
icon : 'fas fa-th-large', icon : 'fas fa-th-large',
gen : function(){ gen : function(){
return [ return dedent`
'<div style=\'column-count:2\'>', ##### Typical Difficulty Classes
'| d10 | Damage Type |', {{column-count="2"
'|:---:|:------------|', | Task Difficulty | DC |
'| 1 | Acid |', |:----------------|:--:|
'| 2 | Cold |', | Very easy | 5 |
'| 3 | Fire |', | Easy | 10 |
'| 4 | Force |', | Medium | 15 |
'| 5 | Lightning |',
'', | Task Difficulty | DC |
'```', |:------------------|:--:|
'```', | Hard | 20 |
'', | Very hard | 25 |
'| d10 | Damage Type |', | Nearly impossible | 30 |
'|:---:|:------------|', }}
'| 6 | Necrotic |', \n`;
'| 7 | Poison |', }
'| 8 | Psychic |',
'| 9 | Radiant |',
'| 10 | Thunder |',
'</div>\n\n',
].join('\n');
},
} }
] ]
}, },

View File

@@ -82,7 +82,7 @@ module.exports = {
`- **Components:** ${components}`, `- **Components:** ${components}`,
`- **Duration:** ${_.sample(['Until dispelled', '1 round', 'Instantaneous', 'Concentration, up to 10 minutes', '1 hour'])}`, `- **Duration:** ${_.sample(['Until dispelled', '1 round', 'Instantaneous', 'Concentration, up to 10 minutes', '1 hour'])}`,
'', '',
'A flame, equivalent in brightness to a torch, springs from from an object that you touch. ', 'A flame, equivalent in brightness to a torch, springs from an object that you touch. ',
'The effect look like a regular flame, but it creates no heat and doesn\'t use oxygen. ', 'The effect look like a regular flame, but it creates no heat and doesn\'t use oxygen. ',
'A *continual flame* can be covered or hidden but not smothered or quenched.', 'A *continual flame* can be covered or hidden but not smothered or quenched.',
'\n\n\n' '\n\n\n'

View File

@@ -55,6 +55,7 @@ const EditPage = createClass({
isSaving : false, isSaving : false,
isPending : false, isPending : false,
alertTrashedGoogleBrew : this.props.brew.trashed, alertTrashedGoogleBrew : this.props.brew.trashed,
alertLoginToTransfer : false,
saveGoogle : this.props.brew.googleId ? true : false, saveGoogle : this.props.brew.googleId ? true : false,
confirmGoogleTransfer : false, confirmGoogleTransfer : false,
errors : null, errors : null,
@@ -140,15 +141,25 @@ const EditPage = createClass({
}, },
handleGoogleClick : function(){ handleGoogleClick : function(){
console.log('handlegoogleclick');
if(!global.account?.googleId) {
this.setState({
alertLoginToTransfer : true
});
return;
}
this.setState((prevState)=>({ this.setState((prevState)=>({
confirmGoogleTransfer : !prevState.confirmGoogleTransfer confirmGoogleTransfer : !prevState.confirmGoogleTransfer
})); }));
this.clearErrors(); this.clearErrors();
}, },
closeAlerts : function(){ closeAlerts : function(event){
event.stopPropagation(); //Only handle click once so alert doesn't reopen
this.setState({ this.setState({
alertTrashedGoogleBrew : false alertTrashedGoogleBrew : false,
alertLoginToTransfer : false,
confirmGoogleTransfer : false
}); });
}, },
@@ -187,7 +198,7 @@ const EditPage = createClass({
.catch((err)=>{ .catch((err)=>{
console.log(err.status === 401 console.log(err.status === 401
? 'Not signed in!' ? 'Not signed in!'
: 'Error Saving to Google!'); : 'Error Transferring to Google!');
this.setState({ errors: err, saveGoogle: false }); this.setState({ errors: err, saveGoogle: false });
}); });
@@ -210,7 +221,7 @@ const EditPage = createClass({
console.log(err.status === 401 console.log(err.status === 401
? 'Not signed in!' ? 'Not signed in!'
: 'Error Saving to Google!'); : 'Error Saving to Google!');
this.setState({ errors: err, saveGoogle: false }); this.setState({ errors: err });
return; return;
}); });
@@ -260,13 +271,19 @@ const EditPage = createClass({
}, },
renderGoogleDriveIcon : function(){ renderGoogleDriveIcon : function(){
if(this.state.saveGoogle) {
return <Nav.item className='googleDriveStorage' onClick={this.handleGoogleClick}> return <Nav.item className='googleDriveStorage' onClick={this.handleGoogleClick}>
<img src={googleDriveActive} alt='googleDriveActive' /> {this.state.saveGoogle
? <img src={googleDriveActive} alt='googleDriveActive'/>
: <img src={googleDriveInactive} alt='googleDriveInactive'/>
}
{this.state.confirmGoogleTransfer && {this.state.confirmGoogleTransfer &&
<div className='errorContainer'> <div className='errorContainer' onClick={this.closeAlerts}>
Would you like to transfer this brew from your Google Drive storage back to the Homebrewery?<br /> { this.state.saveGoogle
? `Would you like to transfer this brew from your Google Drive storage back to the Homebrewery?`
: `Would you like to transfer this brew from the Homebrewery to your personal Google Drive storage?`
}
<br />
<div className='confirm' onClick={this.toggleGoogleStorage}> <div className='confirm' onClick={this.toggleGoogleStorage}>
Yes Yes
</div> </div>
@@ -275,24 +292,23 @@ const EditPage = createClass({
</div> </div>
</div> </div>
} }
</Nav.item>;
} else {
return <Nav.item className='googleDriveStorage' onClick={this.handleGoogleClick}>
<img src={googleDriveInactive} alt='googleDriveInactive' />
{this.state.confirmGoogleTransfer && {this.state.alertLoginToTransfer &&
<div className='errorContainer'> <div className='errorContainer' onClick={this.closeAlerts}>
Would you like to transfer this brew from the Homebrewery to your personal Google Drive storage?<br /> You must be signed in to a Google account to transfer
<div className='confirm' onClick={this.toggleGoogleStorage}> between the homebrewery and Google Drive!
Yes <a target='_blank' rel='noopener noreferrer'
href={`http://naturalcrit.com/login?redirect=${this.state.url}`}>
<div className='confirm'>
Sign In
</div> </div>
</a>
<div className='deny'> <div className='deny'>
No Not Now
</div> </div>
</div> </div>
} }
</Nav.item>; </Nav.item>;
}
}, },
renderSaveButton : function(){ renderSaveButton : function(){
@@ -311,7 +327,7 @@ const EditPage = createClass({
to save this to<br />Google Drive!<br /> to save this to<br />Google Drive!<br />
<a target='_blank' rel='noopener noreferrer' <a target='_blank' rel='noopener noreferrer'
href={`http://naturalcrit.com/login?redirect=${this.state.url}`}> href={`http://naturalcrit.com/login?redirect=${this.state.url}`}>
<div className='confirm' onClick={this.toggleGoogleStorage}> <div className='confirm'>
Sign In Sign In
</div> </div>
</a> </a>

View File

@@ -43,14 +43,14 @@ const NewPage = createClass({
getInitialState : function() { getInitialState : function() {
return { return {
brew : { brew : {
text : this.props.brew.text, text : this.props.brew.text || '',
gDrive : false, gDrive : false,
title : '', title : this.props.brew.title || '',
description : '', description : this.props.brew.description || '',
tags : '', tags : this.props.brew.tags || '',
published : false, published : false,
authors : [], authors : [],
systems : [] systems : this.props.brew.systems || []
}, },
isSaving : false, isSaving : false,

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 864 B

File diff suppressed because one or more lines are too long

View File

@@ -7,7 +7,7 @@
@headerUnderline : #c9ad6a; @headerUnderline : #c9ad6a;
@horizontalRule : #9c2b1b; @horizontalRule : #9c2b1b;
@headerText : #58180D; @headerText : #58180D;
@monsterStatBackground : #FDF1DC; @monsterStatBackground : #EEDBAB;
@page { margin: 0; } @page { margin: 0; }
body { body {
counter-reset : phb-page-numbers; counter-reset : phb-page-numbers;
@@ -17,7 +17,11 @@ body {
} }
.useSansSerif(){ .useSansSerif(){
font-family : ScalySansRemake; font-family : ScalySansRemake;
font-size : 10pt; font-size : 0.325cm;
line-height : 1.2em;
p,dl,ul {
line-height : 1.2em;
}
em{ em{
font-style : italic; font-style : italic;
} }
@@ -29,14 +33,14 @@ body {
.useColumns(@multiplier : 1){ .useColumns(@multiplier : 1){
column-count : 2; column-count : 2;
column-fill : auto; column-fill : auto;
column-gap : 1cm; column-gap : 0.9cm;
column-width : 8cm * @multiplier; column-width : 8cm * @multiplier;
-webkit-column-count : 2; -webkit-column-count : 2;
-moz-column-count : 2; -moz-column-count : 2;
-webkit-column-width : 8cm * @multiplier; -webkit-column-width : 8cm * @multiplier;
-moz-column-width : 8cm * @multiplier; -moz-column-width : 8cm * @multiplier;
-webkit-column-gap : 1cm; -webkit-column-gap : 0.9cm;
-moz-column-gap : 1cm; -moz-column-gap : 0.9cm;
} }
.phb3{ .phb3{
.useColumns(); .useColumns();
@@ -47,11 +51,11 @@ body {
overflow : hidden; overflow : hidden;
height : 279.4mm; height : 279.4mm;
width : 215.9mm; width : 215.9mm;
padding : 1.0cm 1.7cm 1.5cm; padding : 1.4cm 1.9cm 1.7cm;
background-color : @background; background-color : @background;
background-image : @backgroundImage; background-image : @backgroundImage;
font-family : BookInsanityRemake; font-family : BookInsanityRemake;
font-size : 0.317cm; font-size : 0.34cm;
text-rendering : optimizeLegibility; text-rendering : optimizeLegibility;
page-break-before : always; page-break-before : always;
page-break-after : always; page-break-after : always;
@@ -59,11 +63,11 @@ body {
// * BASE // * BASE
// *****************************/ // *****************************/
p{ p{
overflow-wrap : break-word; overflow-wrap : break-word; //TODO: MAKE ALL MARGINS TOP-ONLY. USE * + * STYLE SELECTORS
padding-top : 0em; margin-bottom : 1em;
line-height : 1.3em; line-height : 1.3em;
&+p{ &+p{
padding-top : 0em; margin-top : -1em;
} }
} }
ul{ ul{
@@ -89,7 +93,7 @@ body {
} }
strong{ strong{
font-weight : bold; font-weight : bold;
letter-spacing : 0.03em; letter-spacing : -0.02em;
} }
em{ em{
font-style : italic; font-style : italic;
@@ -108,15 +112,14 @@ body {
// * HEADERS // * HEADERS
// *****************************/ // *****************************/
h1,h2,h3,h4{ h1,h2,h3,h4{
margin-top : 0.2em;
margin-bottom : 0.2em;
font-family : MrEavesRemake; font-family : MrEavesRemake;
font-weight : 800; font-weight : 800;
color : @headerText; color : @headerText;
} }
h1{ h1{
margin-bottom : 0.18cm;
column-span : all; column-span : all;
font-size : 0.987cm; font-size : 0.89cm;
-webkit-column-span : all; -webkit-column-span : all;
-moz-column-span : all; -moz-column-span : all;
&+p::first-letter{ &+p::first-letter{
@@ -136,23 +139,28 @@ body {
color: rgba(0, 0, 0, 0); color: rgba(0, 0, 0, 0);
} }
&+p::first-line{ &+p::first-line{
font-size : .385cm;
font-variant : small-caps; font-variant : small-caps;
} }
} }
h2{ h2{
font-size : 0.705cm; margin-top : 0px;
margin-bottom : 0.05cm;
font-size : 0.75cm;
} }
h3{ h3{
font-size : 0.529cm; margin-top : -0.1cm;
margin-bottom : 0.1cm;
font-size : 0.575cm;
border-bottom : 2px solid @headerUnderline; border-bottom : 2px solid @headerUnderline;
} }
h4{ h4{
margin-bottom : 0.00em; margin-top : -0.02cm;
margin-bottom : 0.02cm;
font-size : 0.458cm; font-size : 0.458cm;
} }
h5{ h5{
margin-bottom : 0.2em; margin-top : -0.02cm;
margin-bottom : 0.02cm;
font-family : ScalySansSmallCapsRemake; font-family : ScalySansSmallCapsRemake;
font-size : 0.423cm; font-size : 0.423cm;
font-weight : 900; font-weight : 900;
@@ -164,21 +172,18 @@ body {
.useSansSerif(); .useSansSerif();
width : 100%; width : 100%;
margin-bottom : 1em; margin-bottom : 1em;
font-size : 10pt;
thead{ thead{
display: table-row-group; display: table-row-group;
font-weight : 800; font-weight : 800;
th{ th{
vertical-align : bottom; vertical-align : bottom;
padding-bottom : 0.3em; padding : 0.14em 0.4em;
padding-right : 0.1em;
padding-left : 0.1em;
} }
} }
tbody{ tbody{
tr{ tr{
td{ td{
padding : 0.3em 0.1em; padding : 0.14em 0.4em;
} }
&:nth-child(odd){ &:nth-child(odd){
background-color : @noteGreen; background-color : @noteGreen;
@@ -213,66 +218,101 @@ body {
//***************************** //*****************************
// * MONSTER STAT BLOCK // * MONSTER STAT BLOCK
// *****************************/ // *****************************/
hr+blockquote{
position : relative; .monster {
padding-top : 15px; &.frame {
background-color : @monsterStatBackground;
border-style : solid; border-style : solid;
border-width : 10px; border-width : 7px 6px;
border-image : @monsterBorderImage 10; background-color : @monsterStatBackground;
background-image : @monsterBlockBackground;
border-image : @monsterBorderImage 14 round;
border-image-outset : 0px 2px;
background-blend-mode : overlay;
background-attachment : fixed;
box-shadow : 1px 4px 14px #888;
padding : 4px 2px;
margin : 0px -6px 1em;
}
.useSansSerif();
//-webkit-transform : translateZ(0); //Prevents shadows from breaking across columns, but breaks internal columns...
position : relative;
padding : 0px;
margin-bottom : 1em;
p{
margin-bottom : 0.3cm;
}
p+p {
margin-top : 0; //May not be needed
text-indent : 0;
}
p:last-of-type {
margin-bottom: 0;
}
//Headers
h2{ h2{
margin-top : -8px; font-size : 0.62cm;
margin-bottom : 0px; line-height : 1em;
&+p{ margin : 0;
padding-bottom : 0px; &+p {
font-size : 0.304cm; //Monster size and type subtext
margin-bottom : 0;
} }
} }
h3{ h3{
font-family : ScalySansRemake; font-family : ScalySansRemake;
font-weight : 400; font-weight : 800;
border-bottom : 1px solid @headerText; font-variant : small-caps;
} border-bottom : 2px solid @headerText;
hr+ul{ margin-top : 0.05cm;
color : @headerText; padding-bottom : 0.05cm;
}
ul{
.useSansSerif();
padding-left : 1em;
font-size : 0.352cm;
}
// Monster Ability table
hr+table{
margin : 0;
column-span : 1;
background-color : transparent;
border-style : none;
border-image : none;
-webkit-column-span : 1;
tbody{
tr:nth-child(odd), tr:nth-child(even){
background-color : transparent;
}
}
}
table{
color : @headerText;
}
p+p{
margin-top : 0em;
padding-bottom : 0.5em;
text-indent : 0em;
} }
//Triangle dividers //Triangle dividers
hr{ hr{
visibility : visible; visibility : visible;
height : 6px; height : 6px;
margin : 4px 0px; margin : 0.12cm 0cm;
background-image : @redTriangleImage; background-image : @redTriangleImage;
background-size : 100% 100%; background-size : 100% 100%;
border : none; border : none;
} }
//Attribute Lists
dl {
.useSansSerif();
color : @headerText;
padding-left :1.3em;
text-indent :-1.3em;
} }
dd {
text-indent : 0px;
}
// Monster Ability table
hr + table:first-of-type{
margin : 0;
column-span : 1;
color : @headerText;
background-color : transparent;
border-style : none;
border-image : none;
-webkit-column-span : 1;
tr {
background-color : transparent;
}
td,th {
padding: 0px;
}
}
}
//Full Width //Full Width
.monster.wide{
.useColumns(0.96);
}
hr+hr+blockquote{ hr+hr+blockquote{
.useColumns(0.96); .useColumns(0.96);
} }
@@ -485,9 +525,15 @@ body {
// * MUSTACHE DIVS/SPANS // * MUSTACHE DIVS/SPANS
// *****************************/ // *****************************/
.phb3 { .phb3 {
.block {
break-inside : avoid;
}
.inline-block { .inline-block {
display : block; display : block;
} }
div {
column-gap : 0.5cm; //Default spacing if a div uses multicolumns
}
} }
//***************************** //*****************************
@@ -512,6 +558,9 @@ body {
// *****************************/ // *****************************/
.phb3 { .phb3 {
.blank { .blank {
height: 0.8em; height: 0.75em;
}
p + .blank {
margin-top: -1em;
} }
} }

View File

@@ -206,7 +206,7 @@ body {
background-color : @monsterStatBackground; background-color : @monsterStatBackground;
border-style : solid; border-style : solid;
border-width : 10px; border-width : 10px;
border-image : @monsterBorderImage 10; border-image : @monsterBorderImageLegacy 10;
h2{ h2{
margin-top : -8px; margin-top : -8px;
margin-bottom : 0px; margin-bottom : 0px;

2358
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.11.1", "version": "2.11.2",
"engines": { "engines": {
"node": "14.15.x" "node": "14.15.x"
}, },
@@ -40,40 +40,42 @@
] ]
}, },
"dependencies": { "dependencies": {
"@babel/core": "^7.13.10", "@babel/core": "^7.14.0",
"@babel/preset-env": "^7.13.10", "@babel/preset-env": "^7.14.0",
"@babel/preset-react": "^7.12.13", "@babel/preset-react": "^7.13.13",
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"classnames": "^2.2.6", "classnames": "^2.3.1",
"codemirror": "^5.59.4", "codemirror": "^5.61.0",
"cookie-parser": "^1.4.5", "cookie-parser": "^1.4.5",
"create-react-class": "^15.7.0", "create-react-class": "^15.7.0",
"dedent-tabs": "^0.9.0",
"express": "^4.17.1", "express": "^4.17.1",
"express-async-handler": "^1.1.4",
"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.1", "googleapis": "73.0.0",
"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", "marked": "2.0.3",
"mongoose": "^5.12.0",
"nanoid": "3.1.21",
"markedLegacy": "npm:marked@^0.3.19", "markedLegacy": "npm:marked@^0.3.19",
"marked": "2.0.1", "moment": "^2.29.1",
"mongoose": "^5.12.7",
"nanoid": "3.1.22",
"nconf": "^0.11.2", "nconf": "^0.11.2",
"prop-types": "15.7.2", "prop-types": "15.7.2",
"query-string": "6.14.1", "query-string": "7.0.0",
"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", "sanitize-filename": "1.6.3",
"superagent": "^6.1.0", "superagent": "^6.1.0",
"vitreum": "github:calculuschild/vitreum#21a8e1c9421f1d3a3b474c12f480feb2fbd28c5b" "vitreum": "git+https://github.com/calculuschild/vitreum.git"
}, },
"devDependencies": { "devDependencies": {
"eslint": "^7.21.0", "eslint": "^7.25.0",
"eslint-plugin-react": "^7.22.0", "eslint-plugin-react": "^7.23.2",
"pico-check": "^2.0.3" "pico-check": "^2.0.3"
} }
} }

232
server.js
View File

@@ -8,6 +8,23 @@ 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'); const sanitizeFilename = require('sanitize-filename');
const asyncHandler = require('express-async-handler');
//Get the brew object from the HB database or Google Drive
const getBrewFromId = asyncHandler(async (id, accessType)=>{
if(accessType !== 'edit' && accessType !== 'share')
throw ('Invalid Access Type when getting brew');
let brew;
if(id.length > 12) {
const googleId = id.slice(0, -12);
id = id.slice(-12);
brew = await GoogleActions.readFileMetadata(config.get('google_api_key'), googleId, id, accessType);
} else {
brew = await HomebrewModel.get(accessType == 'edit' ? { editId: id } : { shareId: id });
brew.sanatize(true);
}
return brew;
});
app.use('/', serveCompressedStaticAssets(`${__dirname}/build`)); app.use('/', serveCompressedStaticAssets(`${__dirname}/build`));
@@ -65,14 +82,10 @@ 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', asyncHandler(async (req, res)=>{
if(req.params.id.length > 12) { const brew = await getBrewFromId(req.params.id, 'share');
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)=>{
const replaceStrings = { '&': '&amp;', '<': '&lt;', '>': '&gt;' }; const replaceStrings = { '&': '&amp;', '<': '&lt;', '>': '&gt;' };
let text = brew.text; let text = brew.text;
for (const replaceStr in replaceStrings) { for (const replaceStr in replaceStrings) {
@@ -80,38 +93,13 @@ app.get('/source/:id', (req, res)=>{
} }
text = `<code><pre style="white-space: pre-wrap;">${text}</pre></code>`; text = `<code><pre style="white-space: pre-wrap;">${text}</pre></code>`;
res.status(200).send(text); res.status(200).send(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)=>{
const replaceStrings = { '&': '&amp;', '<': '&lt;', '>': '&gt;' };
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 //Download brew source page
app.get('/download/:id', (req, res)=>{ app.get('/download/:id', asyncHandler(async (req, res)=>{
const brew = await getBrewFromId(req.params.id, 'share');
const prefix = 'HB - '; 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(' ', ''); let fileName = sanitizeFilename(`${prefix}${brew.title}`).replaceAll(' ', '');
if(!fileName || !fileName.length) { fileName = `${prefix}-Untitled-Brew`; }; if(!fileName || !fileName.length) { fileName = `${prefix}-Untitled-Brew`; };
res.set({ res.set({
@@ -120,29 +108,7 @@ app.get('/download/:id', (req, res)=>{
'Content-Disposition' : `attachment; filename="${fileName}.txt"` 'Content-Disposition' : `attachment; filename="${fileName}.txt"`
}); });
res.status(200).send(brew.text); 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)=>{
console.log(err);
return res.status(404).send('Could not find Homebrew with that id');
});
}
});
//User Page //User Page
app.get('/user/:username', async (req, res, next)=>{ app.get('/user/:username', async (req, res, next)=>{
@@ -170,123 +136,45 @@ app.get('/user/:username', async (req, res, next)=>{
}); });
//Edit Page //Edit Page
app.get('/edit/:id', (req, res, next)=>{ app.get('/edit/:id', asyncHandler(async (req, res, next)=>{
res.header('Cache-Control', 'no-cache, no-store'); //reload the latest saved brew when pressing back button, not the cached version before save. res.header('Cache-Control', 'no-cache, no-store'); //reload the latest saved brew when pressing back button, not the cached version before save.
if(req.params.id.length > 12) { const brew = await getBrewFromId(req.params.id, 'edit');
const googleId = req.params.id.slice(0, -12);
const editId = req.params.id.slice(-12);
GoogleActions.readFileMetadata(config.get('google_api_key'), googleId, editId, 'edit')
.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({ editId: req.params.id })
.then((brew)=>{
req.brew = brew.sanatize();
return next();
})
.catch((err)=>{
console.log(err);
return res.status(400).send(`Can't get that`);
});
}
});
//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; req.brew = brew;
return next(); return next();
}) }));
.catch((err)=>{
console.log(err); //New Page
return res.status(400).send(`Can't get that`); app.get('/new/:id', asyncHandler(async (req, res, next)=>{
}); const brew = await getBrewFromId(req.params.id, 'share');
} req.brew = brew;
}); return next();
}));
//Share Page //Share Page
app.get('/share/:id', (req, res, next)=>{ app.get('/share/:id', asyncHandler(async (req, res, next)=>{
const brew = await getBrewFromId(req.params.id, 'share');
if(req.params.id.length > 12) { if(req.params.id.length > 12) {
const googleId = req.params.id.slice(0, -12); const googleId = req.params.id.slice(0, -12);
const shareId = req.params.id.slice(-12); const shareId = req.params.id.slice(-12);
GoogleActions.readFileMetadata(config.get('google_api_key'), googleId, shareId, 'share') await GoogleActions.increaseView(googleId, shareId, 'share', brew)
.then((brew)=>{ .catch((err)=>{next(err);});
GoogleActions.increaseView(googleId, shareId, 'share', brew);
return brew;
})
.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 { } else {
HomebrewModel.get({ shareId: req.params.id }) await brew.increaseView();
.then((brew)=>{
return brew.increaseView();
})
.then((brew)=>{
req.brew = brew.sanatize(true);
return next();
})
.catch((err)=>{
console.log(err);
return res.status(400).send(`Can't get that`);
});
} }
});
req.brew = brew;
return next();
}));
//Print Page //Print Page
app.get('/print/:id', (req, res, next)=>{ app.get('/print/:id', asyncHandler(async (req, res, next)=>{
if(req.params.id.length > 12) { const brew = await getBrewFromId(req.params.id, 'share');
const googleId = req.params.id.slice(0, -12); req.brew = brew;
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(); 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.sanatize(true);
return next();
})
.catch((err)=>{
console.log(err);
return res.status(400).send(`Can't get that`);
});
}
});
//Render the page //Render the page
//const render = require('.build/render');
const templateFn = require('./client/template.js'); const templateFn = require('./client/template.js');
app.use((req, res)=>{ app.use((req, res)=>{
const props = { const props = {
@@ -303,11 +191,35 @@ app.use((req, res)=>{
templateFn('homebrew', title = req.brew ? req.brew.title : '', props) templateFn('homebrew', title = req.brew ? req.brew.title : '', props)
.then((page)=>{ res.send(page); }) .then((page)=>{ res.send(page); })
.catch((err)=>{ .catch((err)=>{
console.log('TEMPLATE ERROR');
console.log(err); console.log(err);
return res.sendStatus(500); return res.sendStatus(500);
}); });
}); });
//v=====----- Error-Handling Middleware -----=====v//
//Format Errors so all fields will be sent
const replaceErrors = (key, value)=>{
if(value instanceof Error) {
const error = {};
Object.getOwnPropertyNames(value).forEach(function (key) {
error[key] = value[key];
});
return error;
}
return value;
};
const getPureError = (error)=>{
return JSON.parse(JSON.stringify(error, replaceErrors));
};
app.use((err, req, res, next)=>{
const status = err.status || 500;
console.error(err);
res.status(status).send(getPureError(err));
});
//^=====--------------------------------------=====^//
const PORT = process.env.PORT || config.get('web_port') || 8000; const PORT = process.env.PORT || config.get('web_port') || 8000;
app.listen(PORT); app.listen(PORT);

View File

@@ -240,6 +240,7 @@ GoogleActions = {
}, },
readFileMetadata : async (auth, id, accessId, accessType)=>{ readFileMetadata : async (auth, id, accessId, accessType)=>{
const drive = google.drive({ version: 'v3', auth: auth }); const drive = google.drive({ version: 'v3', auth: auth });
const obj = await drive.files.get({ const obj = await drive.files.get({
@@ -248,7 +249,7 @@ GoogleActions = {
}) })
.catch((err)=>{ .catch((err)=>{
console.log('Error loading from Google'); console.log('Error loading from Google');
console.error(err); throw (err);
return; return;
}); });
@@ -345,7 +346,10 @@ GoogleActions = {
increaseView : async (id, accessId, accessType, brew)=>{ increaseView : async (id, accessId, accessType, brew)=>{
//service account because this is modifying another user's file properties //service account because this is modifying another user's file properties
//so we need extended scope //so we need extended scope
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 auth = google.auth.fromJSON(keys); const auth = google.auth.fromJSON(keys);
auth.scopes = ['https://www.googleapis.com/auth/drive']; auth.scopes = ['https://www.googleapis.com/auth/drive'];

View File

@@ -190,7 +190,6 @@ module.exports = {
.replace(/(<dt>.*<\/dt><dd>.*<\/dd>\n?)+/gm, `<dl>$1</dl>\n\n`) .replace(/(<dt>.*<\/dt><dd>.*<\/dd>\n?)+/gm, `<dl>$1</dl>\n\n`)
.replace(/^}}/gm, '\n}}') .replace(/^}}/gm, '\n}}')
.replace(/^({{[^\n]*)$/gm, '$1\n'); .replace(/^({{[^\n]*)$/gm, '$1\n');
console.log(rawBrewText);
return Markdown( return Markdown(
sanatizeScriptTags(rawBrewText), sanatizeScriptTags(rawBrewText),
{ renderer: renderer } { renderer: renderer }