0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2025-12-28 22:12:39 +00:00

Merge branch 'master' into Images-Snippet-Menu

This commit is contained in:
Gazook89
2021-08-14 22:51:40 -05:00
committed by GitHub
18 changed files with 330 additions and 82 deletions

View File

@@ -32,7 +32,7 @@ module.exports = {
skipBlankLines : true,
}],
'max-depth' : ['warn', { max: 4 }],
'max-params' : ['warn', { max: 4 }],
'max-params' : ['warn', { max: 5 }],
'no-restricted-syntax' : ['warn', 'ClassDeclaration', 'SwitchStatement'],
'no-unused-vars' : ['warn', {
vars : 'all',

View File

@@ -57,7 +57,6 @@ module.exports = [
`https://homebrewery.naturalcrit.com/share/${brew.shareId}` +
`&size=100x100) {width:100px;mix-blend-mode:multiply}`;
}
},
{
name : 'Page Number',
@@ -121,13 +120,23 @@ module.exports = [
name : 'Image',
icon : 'fas fa-image',
gen : dedent`
![cat warrior](https://s-media-cache-ak0.pinimg.com/736x/4a/81/79/4a8179462cfdf39054a418efd4cb743e.jpg) {width:325px}
Credit: Kyounghwan Kim`
![cat warrior](https://s-media-cache-ak0.pinimg.com/736x/4a/81/79/4a8179462cfdf39054a418efd4cb743e.jpg) {width:325px,mix-blend-mode:multiply}
{{artist,position:relative,top:-230px,left:-100px,margin-bottom:-30px
##### Cat Warrior
[Kyoung Hwan Kim](https://www.artstation.com/tahra)
}}`
},
{
name : 'Background Image',
icon : 'fas fa-tree',
gen : `![homebrew mug](http://i.imgur.com/hMna6G0.png) {position:absolute,top:50px,right:30px,width:280px}`
gen : dedent`
![homebrew mug](http://i.imgur.com/hMna6G0.png) {position:absolute,top:50px,right:30px,width:280px}
{{artist,top:90px,right:30px
##### Homebrew Mug
[naturalcrit](https://homebrew.naturalcrit.com)
}}`
},
{
name : 'Class Table Decoration',
@@ -217,6 +226,18 @@ module.exports = [
icon : 'fas fa-hat-wizard',
gen : MagicGen.item,
},
{
name : 'Artist Credit',
icon : 'fas fa-signature',
gen : function(){
return dedent`
{{artist,top:90px,right:30px
##### Starry Night
[Van Gogh](https://www.vangoghmuseum.nl/en)
}}
\n`;
},
},
]
},

View File

@@ -171,6 +171,14 @@ module.exports = [
icon : 'far fa-file-word',
gen : CoverPageGen,
},
{
name : 'Artist Credit',
icon : 'fas fa-signature',
gen : '<div class=\'artist\' style=\'top:90px;right:30px;\'>\n' +
'##### Starry Night\n' +
'[Van Gogh](https://www.vangoghmuseum.nl/en)\n' +
'</div>\n'
},
]
},

View File

@@ -322,7 +322,9 @@ const EditPage = createClass({
let errMsg = '';
try {
errMsg += `${this.state.errors.toString()}\n\n`;
errMsg += `\`\`\`\n${JSON.stringify(this.state.errors.response.error, null, ' ')}\n\`\`\``;
errMsg += `\`\`\`\n${this.state.errors.stack}\n`;
errMsg += `${JSON.stringify(this.state.errors.response.error, null, ' ')}\n\`\`\``;
console.log(errMsg);
} catch (e){}
if(this.state.errors.status == '401'){
@@ -344,6 +346,27 @@ const EditPage = createClass({
</Nav.item>;
}
if(this.state.errors.status == '403' && this.state.errors.response.body.errors[0].reason == 'insufficientPermissions'){
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer' onClick={this.clearErrors}>
Looks like your Google credentials have
expired! Visit the log in page to sign out
and sign back in with Google
to save this to Google Drive!
<a target='_blank' rel='noopener noreferrer'
href={`https://www.naturalcrit.com/login?redirect=${this.state.url}`}>
<div className='confirm'>
Sign In
</div>
</a>
<div className='deny'>
Not Now
</div>
</div>
</Nav.item>;
}
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer'>

View File

@@ -61,7 +61,7 @@ const NewPage = createClass({
isSaving : false,
saveGoogle : (global.account && global.account.googleId ? true : false),
errors : [],
errors : null,
htmlErrors : Markdown.validate(this.props.brew.text)
};
},
@@ -138,6 +138,14 @@ const NewPage = createClass({
}));
},
clearErrors : function(){
this.setState({
errors : null,
isSaving : false
});
},
save : async function(){
this.setState({
isSaving : true
@@ -161,7 +169,7 @@ const NewPage = createClass({
console.log(err.status === 401
? 'Not signed in!'
: 'Error Creating New Google Brew!');
this.setState({ isSaving: false });
this.setState({ isSaving: false, errors: err });
return;
});
@@ -191,12 +199,73 @@ const NewPage = createClass({
},
renderSaveButton : function(){
if(this.state.errors){
let errMsg = '';
try {
errMsg += `${this.state.errors.toString()}\n\n`;
errMsg += `\`\`\`\n${this.state.errors.stack}\n`;
errMsg += `${JSON.stringify(this.state.errors.response.error, null, ' ')}\n\`\`\``;
console.log(errMsg);
} catch (e){}
if(this.state.errors.status == '401'){
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer' onClick={this.clearErrors}>
You must be signed in to a Google account
to save this to<br />Google Drive!<br />
<a target='_blank' rel='noopener noreferrer'
href={`https://www.naturalcrit.com/login?redirect=${this.state.url}`}>
<div className='confirm'>
Sign In
</div>
</a>
<div className='deny'>
Not Now
</div>
</div>
</Nav.item>;
}
if(this.state.errors.status == '403' && this.state.errors.response.body.errors[0].reason == 'insufficientPermissions'){
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer' onClick={this.clearErrors}>
Looks like your Google credentials have
expired! Visit the log in page to sign out
and sign back in with Google
to save this to Google Drive!
<a target='_blank' rel='noopener noreferrer'
href={`https://www.naturalcrit.com/login?redirect=${this.state.url}`}>
<div className='confirm'>
Sign In
</div>
</a>
<div className='deny'>
Not Now
</div>
</div>
</Nav.item>;
}
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer'>
Looks like there was a problem saving. <br />
Report the issue <a target='_blank' rel='noopener noreferrer'
href={`https://github.com/naturalcrit/homebrewery/issues/new?body=${encodeURIComponent(errMsg)}`}>
here
</a>.
</div>
</Nav.item>;
}
if(this.state.isSaving){
return <Nav.item icon='fas fa-spinner fa-spin' className='saveButton'>
return <Nav.item icon='fas fa-spinner fa-spin' className='save'>
save...
</Nav.item>;
} else {
return <Nav.item icon='fas fa-save' className='saveButton' onClick={this.save}>
return <Nav.item icon='fas fa-save' className='save' onClick={this.save}>
save
</Nav.item>;
}

View File

@@ -1,10 +1,82 @@
.newPage{
.saveButton{
.navItem.save{
background-color: @orange;
&:hover{
background-color: @green;
}
&.error{
position : relative;
background-color : @red;
}
}
}
.errorContainer{
animation-name: glideDown;
animation-duration: 0.4s;
position : absolute;
top : 100%;
left : 50%;
z-index : 100000;
width : 140px;
padding : 3px;
color : white;
background-color : #333;
border : 3px solid #444;
border-radius : 5px;
transform : translate(-50% + 3px, 10px);
text-align : center;
font-size : 10px;
font-weight : 800;
text-transform : uppercase;
a{
color : @teal;
}
&:before {
content: "";
width: 0px;
height: 0px;
position: absolute;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid transparent;
border-bottom: 10px solid #444;
left: 53px;
top: -23px;
}
&:after {
content: "";
width: 0px;
height: 0px;
position: absolute;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid transparent;
border-bottom: 10px solid #333;
left: 53px;
top: -19px;
}
.deny {
width : 48%;
margin : 1px;
padding : 5px;
background-color : #333;
display : inline-block;
border-left : 1px solid #666;
.animate(background-color);
&:hover{
background-color : red;
}
}
.confirm {
width : 48%;
margin : 1px;
padding : 5px;
background-color : #333;
display : inline-block;
color : white;
.animate(background-color);
&:hover{
background-color : teal;
}
}
}
}

28
package-lock.json generated
View File

@@ -30,8 +30,8 @@
"marked": "2.1.3",
"markedLegacy": "npm:marked@^0.3.19",
"moment": "^2.29.1",
"mongoose": "^5.13.6",
"nanoid": "3.1.23",
"mongoose": "^5.13.7",
"nanoid": "3.1.25",
"nconf": "^0.11.3",
"prop-types": "15.7.2",
"query-string": "7.0.1",
@@ -6321,9 +6321,9 @@
}
},
"node_modules/mongoose": {
"version": "5.13.6",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.6.tgz",
"integrity": "sha512-IyswXkgxnnl+rpiU+lzXl5/BOEle2llDfuPBrN6K+Eb5vS6a/HN/A9zrdtOcSTb0tVoCZ0QN5PfDSwa/EEGBuQ==",
"version": "5.13.7",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.7.tgz",
"integrity": "sha512-ADIvftZ+KfoTALMZ0n8HvBlezFhcUd73hQaHQDwQ+3X+JZlqE47fUy9yhFZ2SjT+qzmuaCcIXCfhewIc38t2fQ==",
"dependencies": {
"@types/mongodb": "^3.5.27",
"bson": "^1.1.4",
@@ -6405,9 +6405,9 @@
"optional": true
},
"node_modules/nanoid": {
"version": "3.1.23",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz",
"integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==",
"version": "3.1.25",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz",
"integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==",
"bin": {
"nanoid": "bin/nanoid.cjs"
},
@@ -14345,9 +14345,9 @@
}
},
"mongoose": {
"version": "5.13.6",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.6.tgz",
"integrity": "sha512-IyswXkgxnnl+rpiU+lzXl5/BOEle2llDfuPBrN6K+Eb5vS6a/HN/A9zrdtOcSTb0tVoCZ0QN5PfDSwa/EEGBuQ==",
"version": "5.13.7",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.7.tgz",
"integrity": "sha512-ADIvftZ+KfoTALMZ0n8HvBlezFhcUd73hQaHQDwQ+3X+JZlqE47fUy9yhFZ2SjT+qzmuaCcIXCfhewIc38t2fQ==",
"requires": {
"@types/mongodb": "^3.5.27",
"bson": "^1.1.4",
@@ -14420,9 +14420,9 @@
"optional": true
},
"nanoid": {
"version": "3.1.23",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz",
"integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw=="
"version": "3.1.25",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz",
"integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q=="
},
"nanomatch": {
"version": "1.2.13",

View File

@@ -61,8 +61,8 @@
"marked": "2.1.3",
"markedLegacy": "npm:marked@^0.3.19",
"moment": "^2.29.1",
"mongoose": "^5.13.6",
"nanoid": "3.1.23",
"mongoose": "^5.13.7",
"nanoid": "3.1.25",
"nconf": "^0.11.3",
"prop-types": "15.7.2",
"query-string": "7.0.1",

View File

@@ -168,6 +168,7 @@ GoogleActions = {
.catch((err)=>{
console.log('Error saving to google');
console.error(err);
throw (err);
//return res.status(500).send('Error while saving');
});
}
@@ -203,8 +204,9 @@ GoogleActions = {
media : media
})
.catch((err)=>{
console.log('Error while creating new Google brew');
console.error(err);
return res.status(500).send('Error while creating google brew');
throw (err);
});
if(!obj) return;

View File

@@ -141,9 +141,12 @@ const newGoogleBrew = async (req, res, next)=>{
req.body = brew;
const newBrew = await GoogleActions.newGoogleBrew(oAuth2Client, brew);
return res.status(200).send(newBrew);
try {
const newBrew = await GoogleActions.newGoogleBrew(oAuth2Client, brew);
return res.status(200).send(newBrew);
} catch (err) {
return res.status(err.response.status).send(err);
}
};
const updateGoogleBrew = async (req, res, next)=>{
@@ -154,9 +157,12 @@ const updateGoogleBrew = async (req, res, next)=>{
const brew = req.body;
brew.text = mergeBrewText(brew.text, brew.style);
const updatedBrew = await GoogleActions.updateGoogleBrew(oAuth2Client, brew);
return res.status(200).send(updatedBrew);
try {
const updatedBrew = await GoogleActions.updateGoogleBrew(oAuth2Client, brew);
return res.status(200).send(updatedBrew);
} catch (err) {
return res.status(err.response.status).send(err);
}
};
router.post('/api', newBrew);

View File

@@ -47,12 +47,6 @@ const CodeEditor = createClass({
indentWithTabs : true,
tabSize : 2,
extraKeys : {
'Ctrl-B' : this.makeBold,
'Cmd-B' : this.makeBold,
'Ctrl-I' : this.makeItalic,
'Cmd-I' : this.makeItalic,
'Ctrl-M' : this.makeSpan,
'Cmd-M' : this.makeSpan,
'Ctrl-B' : this.makeBold,
'Cmd-B' : this.makeBold,
'Ctrl-I' : this.makeItalic,
@@ -60,7 +54,7 @@ const CodeEditor = createClass({
'Ctrl-M' : this.makeSpan,
'Cmd-M' : this.makeSpan,
'Ctrl-/' : this.makeComment,
'Cmd-/' : this.makeComment,
'Cmd-/' : this.makeComment
}
});

View File

@@ -369,45 +369,28 @@ const getTableCell = (text, cell, type, align)=>{
};
const splitCells = (tableRow, count, prevRow = [])=>{
// trim any excessive pipes at start of row
tableRow = tableRow.replace(/^\|+(?=\|)/, '')
.replace(/(\|+)/g, (match, p1, offset, str)=>{
let escaped = false,
curr = offset;
while (--curr >= 0 && str[curr] === '\\') escaped = !escaped;
if(escaped) {
// odd number of slashes means | is escaped
// so we leave it and the slashes alone
return p1;
} else {
// add space before unescaped | to distinguish it from an escaped pipe
return ` ${p1}`;
}
});
const cells = [...tableRow.matchAll(/(?:[^|\\]|\\.?)+(?:\|+|$)/g)].map((x)=>x[0]);
const cells = tableRow.split(/(?: \||(?<=\|)\|)(?=[^\|]|$)/g);
let i = 0;
// First/last cell in a row cannot be empty if it has no leading/trailing pipe
if(!cells[0].trim()) { cells.shift(); }
if(!cells[cells.length - 1].trim()) { cells.pop(); }
// Remove first/last cell in a row if whitespace only and no leading/trailing pipe
if(!cells[0]?.trim()) { cells.shift(); }
if(!cells[cells.length - 1]?.trim()) { cells.pop(); }
let numCols = 0;
let i, j, trimmedCell, prevCell, prevCols;
for (; i < cells.length; i++) {
const trimmedCell = cells[i].split(/ \|+$/)[0];
for (i = 0; i < cells.length; i++) {
trimmedCell = cells[i].split(/\|+$/)[0];
cells[i] = {
rowspan : 1,
colspan : Math.max(cells[i].length - trimmedCell.length, 1),
text : trimmedCell.trim().replace(/\\\|/g, '|')
// trim whitespace and display escaped pipes as normal character
// display escaped pipes as normal character
};
// Handle Rowspan
if(trimmedCell.slice(-1) == '^' && prevRow.length) {
// Find matching cell in previous row
let prevCols = 0;
let j, prevCell;
prevCols = 0;
for (j = 0; j < prevRow.length; j++) {
prevCell = prevRow[j];
if((prevCols == numCols) && (prevCell.colspan == cells[i].colspan)) {

View File

@@ -2,12 +2,13 @@
@import (less) './themes/assets/assets.less';
//Colors
@background : #EEE5CE;
@noteGreen : #e0e5c1;
@headerUnderline : #c9ad6a;
@horizontalRule : #9c2b1b;
@headerText : #58180D;
@monsterStatBackground : #EEDBAB;
@background : #EEE5CE; // Light parchment
@noteGreen : #e0e5c1; // Pastel green
@headerUnderline : #c9ad6a; // Gold
@horizontalRule : #9c2b1b; // Maroon
@headerText : #58180D; // Dark maroon
@monsterStatBackground : #EEDBAB; // Light orange parchment
@captionText : #766649; // Brown
@page { margin: 0; }
body {
counter-reset : phb-page-numbers;
@@ -263,6 +264,33 @@ body {
margin-bottom : 0em;
}
}
//*****************************
// * ARTIST CREDIT BLOCK
// *****************************/
.artist {
position : absolute;
text-align : center;
font-family : WalterTurncoat;
font-size : 0.27cm;
color : @captionText;
p, p + p {
margin : unset;
text-indent : unset;
line-height : 1em;
}
h5 {
font-size : 1.3em;
font-family : WalterTurncoat;
}
a{
color : inherit;
text-decoration : unset;
&:hover {
text-decoration : underline;
}
}
}
//*****************************
// * MONSTER STAT BLOCK
// *****************************/

View File

@@ -2,12 +2,13 @@
@import (less) './themes/assets/assets.less';
@import (less) './themes/phb.depricated.less';
//Colors
@background : #EEE5CE;
@noteGreen : #e0e5c1;
@headerUnderline : #c9ad6a;
@horizontalRule : #9c2b1b;
@headerText : #58180D;
@monsterStatBackground : #FDF1DC;
@background : #EEE5CE; // Light parchment
@noteGreen : #e0e5c1; // Pastel green
@headerUnderline : #c9ad6a; // Gold
@horizontalRule : #9c2b1b; // Maroon
@headerText : #58180D; // Dark maroon
@monsterStatBackground : #FDF1DC; // Lighter parchment
@captionText : #766649; // Brown
@page { margin: 0; }
body {
counter-reset : phb-page-numbers;
@@ -445,6 +446,35 @@ body {
.phb pre+.descriptive{
margin-top : 8px;
}
//*****************************
// * ARTIST CREDIT BLOCK
// *****************************/
.phb {
.artist {
position : absolute;
text-align : center;
font-family : WalterTurncoat;
font-size : 0.27cm;
color : @captionText;
p, p + p {
margin : unset;
text-indent : unset;
line-height : 1em;
}
h5 {
font-size : 1.3em;
font-family : WalterTurncoat;
}
a{
color : inherit;
text-decoration : unset;
&:hover {
text-decoration : underline;
}
}
}
}
//*****************************
// * TABLE OF CONTENTS
// *****************************/

Binary file not shown.

View File

@@ -37,6 +37,12 @@
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: WalterTurncoat;
src: url('../fonts/5e legacy/WalterTurncoat-Regular.woff2');
font-weight: normal;
font-style: normal;
}
/* Headers */
@font-face {

Binary file not shown.

View File

@@ -55,6 +55,12 @@
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: WalterTurncoat;
src: url('../fonts/5e/WalterTurncoat-Regular.woff2');
font-weight: normal;
font-style: normal;
}
/* Headers */
@font-face {