0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2026-01-27 22:33:07 +00:00

Merge commit '2661e2cf' into PRODUCTION

This commit is contained in:
Trevor Buckner
2021-07-12 21:44:17 -04:00
20 changed files with 1925 additions and 2577 deletions

View File

@@ -6,6 +6,27 @@ h5 {
# changelog # changelog
### Saturday, 28/6/2021 - v2.13.1
- Fixed the issue with new brews not saving!
### Saturday, 26/6/2021 - v2.13.0
- "Share to Reddit" button now works with Google brews
- Downloading or viewing the source of your brew will now show the contents of the Style tab at the top of the document in a backtick code fence like this:
\`\`\`css
myStyle {color: black}
\`\`\`
##### G-Ambatte :
- New **Download**, **View**, and **Clone to New** buttons in the "Source" dropdown on the Share page.
- Pasting your brew into a "New" page and saving will transfer any CSS in the code fence to the Style tab.
- Unsaved work in the New page Style tab is now cached to your browser storage if you navigate away.
### Thursday, 10/6/2021 - v2.12.0 ### Thursday, 10/6/2021 - v2.12.0
- New "style" tab to better organize custom CSS in preparation for new themes and sharable styles. - New "style" tab to better organize custom CSS in preparation for new themes and sharable styles.

View File

@@ -23,7 +23,7 @@ const NotificationPopup = createClass({
psa : function(){ psa : function(){
return <li key='psa'> return <li key='psa'>
<em>Google Drive Integration!</em> <br /> <em>Google Drive Integration!</em> <br />
We have added Google Drive integration to the Homebrewery! <a target='_blank' href='http://naturalcrit.com/login'>Sign in</a> with We have added Google Drive integration to the Homebrewery! <a target='_blank' href='https://www.naturalcrit.com/login'>Sign in</a> 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 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 storage, and Google will keep a backup of each version! No more lost work surprises!
<br /><br /> <br /><br />

View File

@@ -3,17 +3,26 @@ const React = require('react');
const createClass = require('create-react-class'); const createClass = require('create-react-class');
const _ = require('lodash'); const _ = require('lodash');
const cx = require('classnames'); const cx = require('classnames');
const dedent = require('dedent-tabs').default;
const CodeEditor = require('naturalcrit/codeEditor/codeEditor.jsx'); const CodeEditor = require('naturalcrit/codeEditor/codeEditor.jsx');
const SnippetBar = require('./snippetbar/snippetbar.jsx'); const SnippetBar = require('./snippetbar/snippetbar.jsx');
const MetadataEditor = require('./metadataEditor/metadataEditor.jsx'); const MetadataEditor = require('./metadataEditor/metadataEditor.jsx');
const SNIPPETBAR_HEIGHT = 25;
const DEFAULT_STYLE_TEXT = dedent`
/*=======--- Example CSS styling ---=======*/
/* Any CSS here will apply to your document! */
.myExampleClass {
color: black;
}`;
const splice = function(str, index, inject){ const splice = function(str, index, inject){
return str.slice(0, index) + inject + str.slice(index); return str.slice(0, index) + inject + str.slice(index);
}; };
const SNIPPETBAR_HEIGHT = 25;
const Editor = createClass({ const Editor = createClass({
getDefaultProps : function() { getDefaultProps : function() {
@@ -176,7 +185,7 @@ const Editor = createClass({
return <CodeEditor key='style' return <CodeEditor key='style'
ref='codeEditor' ref='codeEditor'
language='css' language='css'
value={this.props.brew.style} value={this.props.brew.style ?? DEFAULT_STYLE_TEXT}
onChange={this.props.onStyleChange} />; onChange={this.props.onStyleChange} />;
} }
if(this.isMeta()){ if(this.isMeta()){

View File

@@ -67,10 +67,12 @@ const MetadataEditor = createClass({
getRedditLink : function(){ getRedditLink : function(){
const meta = this.props.metadata; const meta = this.props.metadata;
const shareLink = (meta.googleId || '') + meta.shareId;
const title = `${meta.title} [${meta.systems.join(' ')}]`; const title = `${meta.title} [${meta.systems.join(' ')}]`;
const text = `Hey guys! I've been working on this homebrew. I'd love your feedback. Check it out. const text = `Hey guys! I've been working on this homebrew. I'd love your feedback. Check it out.
**[Homebrewery Link](http://homebrewery.naturalcrit.com/share/${meta.shareId})**`; **[Homebrewery Link](https://homebrewery.naturalcrit.com/share/${shareLink})**`;
return `https://www.reddit.com/r/UnearthedArcana/submit?title=${encodeURIComponent(title)}&text=${encodeURIComponent(text)}`; return `https://www.reddit.com/r/UnearthedArcana/submit?title=${encodeURIComponent(title)}&text=${encodeURIComponent(text)}`;
}, },

View File

@@ -1,7 +1,7 @@
@import 'naturalcrit/styles/core.less'; @import 'naturalcrit/styles/core.less';
.homebrew{ .homebrew{
height : 100%; height : 100%;
.page{ .sitePage{
display : flex; display : flex;
height : 100%; height : 100%;
background-color : @steel; background-color : @steel;

View File

@@ -25,7 +25,7 @@ const Account = createClass({
</Nav.item>; </Nav.item>;
} }
return <Nav.item href={`http://naturalcrit.com/login?redirect=${this.state.url}`} color='teal' icon='fas fa-sign-in-alt'> return <Nav.item href={`https://www.naturalcrit.com/login?redirect=${this.state.url}`} color='teal' icon='fas fa-sign-in-alt'>
login login
</Nav.item>; </Nav.item>;
} }

View File

@@ -304,7 +304,7 @@ const EditPage = createClass({
You must be signed in to a Google account to transfer You must be signed in to a Google account to transfer
between the homebrewery and Google Drive! between the homebrewery and Google Drive!
<a target='_blank' rel='noopener noreferrer' <a target='_blank' rel='noopener noreferrer'
href={`http://naturalcrit.com/login?redirect=${this.state.url}`}> href={`https://www.naturalcrit.com/login?redirect=${this.state.url}`}>
<div className='confirm'> <div className='confirm'>
Sign In Sign In
</div> </div>
@@ -332,7 +332,7 @@ const EditPage = createClass({
You must be signed in to a Google account You must be signed in to a Google account
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={`https://www.naturalcrit.com/login?redirect=${this.state.url}`}>
<div className='confirm'> <div className='confirm'>
Sign In Sign In
</div> </div>
@@ -349,7 +349,7 @@ const EditPage = createClass({
<div className='errorContainer'> <div className='errorContainer'>
Looks like there was a problem saving. <br /> Looks like there was a problem saving. <br />
Report the issue <a target='_blank' rel='noopener noreferrer' Report the issue <a target='_blank' rel='noopener noreferrer'
href={`https://github.com/naturalcrt/naturalcrit/issues/new?body=${encodeURIComponent(errMsg)}`}> href={`https://github.com/naturalcrit/homebrewery/issues/new?body=${encodeURIComponent(errMsg)}`}>
here here
</a>. </a>.
</div> </div>
@@ -406,7 +406,7 @@ const EditPage = createClass({
}, },
render : function(){ render : function(){
return <div className='editPage page'> return <div className='editPage sitePage'>
<Meta name='robots' content='noindex, nofollow' /> <Meta name='robots' content='noindex, nofollow' />
{this.renderNavbar()} {this.renderNavbar()}

View File

@@ -23,7 +23,7 @@ const ErrorPage = createClass({
text : '# Oops \n We could not find a brew with that id. **Sorry!**', text : '# Oops \n We could not find a brew with that id. **Sorry!**',
render : function(){ render : function(){
return <div className='errorPage page'> return <div className='errorPage sitePage'>
<Navbar ver={this.props.ver}> <Navbar ver={this.props.ver}>
<Nav.section> <Nav.section>
<Nav.item className='errorTitle'> <Nav.item className='errorTitle'>

View File

@@ -72,7 +72,7 @@ const HomePage = createClass({
}, },
render : function(){ render : function(){
return <div className='homePage page'> return <div className='homePage sitePage'>
<Meta name='google-site-verification' content='NwnAQSSJZzAT7N-p5MY6ydQ7Njm67dtbu73ZSyE5Fy4' /> <Meta name='google-site-verification' content='NwnAQSSJZzAT7N-p5MY6ydQ7Njm67dtbu73ZSyE5Fy4' />
{this.renderNavbar()} {this.renderNavbar()}

View File

@@ -1,9 +1,9 @@
/*eslint max-lines: ["warn", {"max": 300, "skipBlankLines": true, "skipComments": true}]*/
require('./newPage.less'); require('./newPage.less');
const React = require('react'); const React = require('react');
const createClass = require('create-react-class'); const createClass = require('create-react-class');
const _ = require('lodash'); const _ = require('lodash');
const request = require('superagent'); const request = require('superagent');
const dedent = require('dedent-tabs').default;
const Markdown = require('naturalcrit/markdown.js'); const Markdown = require('naturalcrit/markdown.js');
@@ -17,20 +17,15 @@ const SplitPane = require('naturalcrit/splitPane/splitPane.jsx');
const Editor = require('../../editor/editor.jsx'); const Editor = require('../../editor/editor.jsx');
const BrewRenderer = require('../../brewRenderer/brewRenderer.jsx'); const BrewRenderer = require('../../brewRenderer/brewRenderer.jsx');
const KEY = 'homebrewery-new'; const BREWKEY = 'homebrewery-new';
const STYLEKEY = 'homebrewery-new-style';
const NewPage = createClass({ const NewPage = createClass({
getDefaultProps : function() { getDefaultProps : function() {
return { return {
brew : { brew : {
text : '', text : '',
style : dedent`
/*=======--- Example CSS styling ---=======*/
/* Any CSS here will apply to your document! */
.myExampleClass {
color: black;
}`,
shareId : null, shareId : null,
editId : null, editId : null,
createdAt : null, createdAt : null,
@@ -51,7 +46,6 @@ const NewPage = createClass({
return { return {
brew : { brew : {
text : this.props.brew.text || '', text : this.props.brew.text || '',
style : this.props.brew.style || '',
gDrive : false, gDrive : false,
title : this.props.brew.title || '', title : this.props.brew.title || '',
description : this.props.brew.description || '', description : this.props.brew.description || '',
@@ -70,10 +64,15 @@ const NewPage = createClass({
}, },
componentDidMount : function() { componentDidMount : function() {
const storage = localStorage.getItem(KEY); const brewStorage = localStorage.getItem(BREWKEY);
if(!this.props.brew.text && storage){ const styleStorage = localStorage.getItem(STYLEKEY);
if(!this.props.brew.text || !this.props.brew.style){
this.setState({ this.setState({
brew : { text: storage } brew : {
text : this.props.brew.text || (brewStorage ?? ''),
style : this.props.brew.style || (styleStorage ?? undefined)
}
}); });
} }
@@ -112,13 +111,14 @@ const NewPage = createClass({
brew : _.merge({}, prevState.brew, { text: text }), brew : _.merge({}, prevState.brew, { text: text }),
htmlErrors : htmlErrors htmlErrors : htmlErrors
})); }));
localStorage.setItem(KEY, text); localStorage.setItem(BREWKEY, text);
}, },
handleStyleChange : function(style){ handleStyleChange : function(style){
this.setState((prevState)=>({ this.setState((prevState)=>({
brew : _.merge({}, prevState.brew, { style: style }), brew : _.merge({}, prevState.brew, { style: style }),
})); }));
localStorage.setItem(STYLEKEY, style);
}, },
handleMetaChange : function(metadata){ handleMetaChange : function(metadata){
@@ -135,10 +135,18 @@ const NewPage = createClass({
console.log('saving new brew'); console.log('saving new brew');
let brew = this.state.brew;
// Split out CSS to Style if CSS codefence exists
if(brew.text.startsWith('```css') && brew.text.indexOf('```\n\n') > 0) {
const index = brew.text.indexOf('```\n\n');
brew.style = `${brew.style ? `${brew.style}\n` : ''}${brew.text.slice(7, index - 1)}`;
brew.text = brew.text.slice(index + 5);
};
if(this.state.saveGoogle) { if(this.state.saveGoogle) {
const res = await request const res = await request
.post('/api/newGoogle/') .post('/api/newGoogle/')
.send(this.state.brew) .send(brew)
.catch((err)=>{ .catch((err)=>{
console.log(err.status === 401 console.log(err.status === 401
? 'Not signed in!' ? 'Not signed in!'
@@ -147,12 +155,13 @@ const NewPage = createClass({
return; return;
}); });
const brew = res.body; brew = res.body;
localStorage.removeItem(KEY); localStorage.removeItem(BREWKEY);
localStorage.removeItem(STYLEKEY);
window.location = `/edit/${brew.googleId}${brew.editId}`; window.location = `/edit/${brew.googleId}${brew.editId}`;
} else { } else {
request.post('/api') request.post('/api')
.send(this.state.brew) .send(brew)
.end((err, res)=>{ .end((err, res)=>{
if(err){ if(err){
this.setState({ this.setState({
@@ -161,8 +170,9 @@ const NewPage = createClass({
return; return;
} }
window.onbeforeunload = function(){}; window.onbeforeunload = function(){};
const brew = res.body; brew = res.body;
localStorage.removeItem(KEY); localStorage.removeItem(BREWKEY);
localStorage.removeItem(STYLEKEY);
window.location = `/edit/${brew.editId}`; window.location = `/edit/${brew.editId}`;
}); });
} }
@@ -181,7 +191,7 @@ const NewPage = createClass({
}, },
print : function(){ print : function(){
localStorage.setItem('print', this.state.brew.text); localStorage.setItem('print', `<style>\n${this.state.brew.style}\n</style>\n\n${this.state.brew.text}`);
window.open('/print?dialog=true&local=print', '_blank'); window.open('/print?dialog=true&local=print', '_blank');
}, },
@@ -209,7 +219,7 @@ const NewPage = createClass({
}, },
render : function(){ render : function(){
return <div className='newPage page'> return <div className='newPage sitePage'>
{this.renderNavbar()} {this.renderNavbar()}
<div className='content'> <div className='content'>
<SplitPane onDragFinish={this.handleSplitMove} ref='pane'> <SplitPane onDragFinish={this.handleSplitMove} ref='pane'>

View File

@@ -39,7 +39,7 @@ const PrintPage = createClass({
if(this.props.brew.renderer == 'legacy') { if(this.props.brew.renderer == 'legacy') {
return _.map(this.state.brewText.split('\\page'), (page, index)=>{ return _.map(this.state.brewText.split('\\page'), (page, index)=>{
return <div return <div
className='phb' className='phb page'
id={`p${index + 1}`} id={`p${index + 1}`}
dangerouslySetInnerHTML={{ __html: MarkdownLegacy.render(page) }} dangerouslySetInnerHTML={{ __html: MarkdownLegacy.render(page) }}
key={index} />; key={index} />;
@@ -47,7 +47,7 @@ const PrintPage = createClass({
} else { } else {
return _.map(this.state.brewText.split(/^\\page/gm), (page, index)=>{ return _.map(this.state.brewText.split(/^\\page/gm), (page, index)=>{
return <div return <div
className='phb3' className='phb3 page'
id={`p${index + 1}`} id={`p${index + 1}`}
dangerouslySetInnerHTML={{ __html: Markdown.render(page) }} dangerouslySetInnerHTML={{ __html: Markdown.render(page) }}
key={index} />; key={index} />;

View File

@@ -29,6 +29,12 @@ const SharePage = createClass({
}; };
}, },
getInitialState : function() {
return {
showDropdown : false
};
},
componentDidMount : function() { componentDidMount : function() {
document.addEventListener('keydown', this.handleControlKeys); document.addEventListener('keydown', this.handleControlKeys);
}, },
@@ -51,8 +57,30 @@ const SharePage = createClass({
this.props.brew.shareId; this.props.brew.shareId;
}, },
handleDropdown : function(show){
this.setState({
showDropdown : show
});
},
renderDropdown : function(){
if(!this.state.showDropdown) return null;
return <div className='dropdown'>
<a href={`/source/${this.processShareId()}`} className='item'>
view
</a>
<a href={`/download/${this.processShareId()}`} className='item'>
download
</a>
<a href={`/new/${this.processShareId()}`} className='item'>
clone to new
</a>
</div>;
},
render : function(){ render : function(){
return <div className='sharePage page'> return <div className='sharePage sitePage'>
<Meta name='robots' content='noindex, nofollow' /> <Meta name='robots' content='noindex, nofollow' />
<Navbar> <Navbar>
<Nav.section> <Nav.section>
@@ -61,11 +89,11 @@ const SharePage = createClass({
<Nav.section> <Nav.section>
<PrintLink shareId={this.processShareId()} /> <PrintLink shareId={this.processShareId()} />
<Nav.item href={`/source/${this.processShareId()}`} color='teal' icon='fas fa-code'> <Nav.item icon='fas fa-code' color='red' className='source'
onMouseEnter={()=>this.handleDropdown(true)}
onMouseLeave={()=>this.handleDropdown(false)}>
source source
</Nav.item> {this.renderDropdown()}
<Nav.item href={`/download/${this.processShareId()}`} color='red' icon='fas fa-download'>
download
</Nav.item> </Nav.item>
<RecentNavItem brew={this.props.brew} storageKey='view' /> <RecentNavItem brew={this.props.brew} storageKey='view' />
<Account /> <Account />

View File

@@ -2,4 +2,49 @@
.content{ .content{
overflow-y : hidden; overflow-y : hidden;
} }
.source.navItem{
position : relative;
.dropdown{
position : absolute;
top : 28px;
left : 0px;
z-index : 10000;
width : 100%;
h4{
display : block;
box-sizing : border-box;
padding : 5px 0px;
background-color : #333;
font-size : 0.8em;
color : #bbb;
text-align : center;
border-top : 1px solid #888;
&:nth-of-type(1){ background-color: darken(@teal, 20%); }
&:nth-of-type(2){ background-color: darken(@purple, 30%); }
}
.item{
.animate(background-color);
position : relative;
display : block;
width : 100%;
vertical-align : middle;
padding : 13px 5px;
box-sizing : border-box;
background-color : #333;
color : white;
text-decoration : none;
border-top : 1px solid #888;
&:hover{
background-color : @blue;
}
.title{
display : inline-block;
overflow : hidden;
width : 100%;
text-overflow : ellipsis;
white-space : nowrap;
}
}
}
}
} }

View File

@@ -52,7 +52,7 @@ const UserPage = createClass({
render : function(){ render : function(){
const brews = this.getSortedBrews(); const brews = this.getSortedBrews();
return <div className='userPage page'> return <div className='userPage sitePage'>
<Navbar> <Navbar>
<Nav.section> <Nav.section>
<NewBrew /> <NewBrew />

4228
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.12.0", "version": "2.13.1",
"engines": { "engines": {
"node": "14.15.x" "node": "14.15.x"
}, },
@@ -40,32 +40,32 @@
] ]
}, },
"dependencies": { "dependencies": {
"@babel/core": "^7.14.3", "@babel/core": "^7.14.6",
"@babel/plugin-transform-runtime": "^7.14.5", "@babel/plugin-transform-runtime": "^7.14.5",
"@babel/preset-env": "^7.14.4", "@babel/preset-env": "^7.14.7",
"@babel/preset-react": "^7.13.13", "@babel/preset-react": "^7.14.5",
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"classnames": "^2.3.1", "classnames": "^2.3.1",
"codemirror": "^5.61.1", "codemirror": "^5.62.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", "dedent-tabs": "^0.9.0",
"express": "^4.17.1", "express": "^4.17.1",
"express-async-handler": "^1.1.4", "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": "10.0.0",
"googleapis": "75.0.0", "googleapis": "78.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",
"marked": "2.0.6", "marked": "2.1.3",
"markedLegacy": "npm:marked@^0.3.19", "markedLegacy": "npm:marked@^0.3.19",
"moment": "^2.29.1", "moment": "^2.29.1",
"mongoose": "^5.12.12", "mongoose": "^5.12.15",
"nanoid": "3.1.23", "nanoid": "3.1.23",
"nconf": "^0.11.2", "nconf": "^0.11.3",
"prop-types": "15.7.2", "prop-types": "15.7.2",
"query-string": "7.0.0", "query-string": "7.0.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",
@@ -75,8 +75,8 @@
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git" "vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
}, },
"devDependencies": { "devDependencies": {
"eslint": "^7.27.0", "eslint": "^7.29.0",
"eslint-plugin-react": "^7.23.2", "eslint-plugin-react": "^7.24.0",
"pico-check": "^2.1.3" "pico-check": "^2.1.3"
} }
} }

View File

@@ -9,11 +9,12 @@ 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'); const asyncHandler = require('express-async-handler');
const dedent = require('dedent-tabs').default;
const brewAccessTypes = ['edit', 'share', 'raw'];
//Get the brew object from the HB database or Google Drive //Get the brew object from the HB database or Google Drive
const getBrewFromId = asyncHandler(async (id, accessType)=>{ const getBrewFromId = asyncHandler(async (id, accessType)=>{
if(accessType !== 'edit' && accessType !== 'share') if(!brewAccessTypes.includes(accessType))
throw ('Invalid Access Type when getting brew'); throw ('Invalid Access Type when getting brew');
let brew; let brew;
if(id.length > 12) { if(id.length > 12) {
@@ -22,23 +23,19 @@ const getBrewFromId = asyncHandler(async (id, accessType)=>{
brew = await GoogleActions.readFileMetadata(config.get('google_api_key'), googleId, id, accessType); brew = await GoogleActions.readFileMetadata(config.get('google_api_key'), googleId, id, accessType);
} else { } else {
brew = await HomebrewModel.get(accessType == 'edit' ? { editId: id } : { shareId: id }); brew = await HomebrewModel.get(accessType == 'edit' ? { editId: id } : { shareId: id });
brew = brew.toObject(); brew = brew.toObject(); // Convert MongoDB object to standard Javascript Object
} }
brew = sanitizeBrew(brew, accessType === 'edit' ? false : true); brew = sanitizeBrew(brew, accessType === 'edit' ? false : true);
//Split brew.text into text and style //Split brew.text into text and style
//unless the Access Type is RAW, in which case return immediately
if(accessType == 'raw') {
return brew;
}
if(brew.text.startsWith('```css')) { if(brew.text.startsWith('```css')) {
const index = brew.text.indexOf('```\n\n'); const index = brew.text.indexOf('```\n\n');
brew.style = brew.text.slice(7, index - 1); brew.style = brew.text.slice(7, index - 1);
brew.text = brew.text.slice(index + 5); brew.text = brew.text.slice(index + 5);
} else {
brew.style = dedent`
/*=======--- Example CSS styling ---=======*/
/* Any CSS here will apply to your document! */
.myExampleClass {
color: black;
}`;
} }
return brew; return brew;
}); });
@@ -110,7 +107,7 @@ app.get('/robots.txt', (req, res)=>{
//Source page //Source page
app.get('/source/:id', asyncHandler(async (req, res)=>{ app.get('/source/:id', asyncHandler(async (req, res)=>{
const brew = await getBrewFromId(req.params.id, 'share'); const brew = await getBrewFromId(req.params.id, 'raw');
const replaceStrings = { '&': '&amp;', '<': '&lt;', '>': '&gt;' }; const replaceStrings = { '&': '&amp;', '<': '&lt;', '>': '&gt;' };
let text = brew.text; let text = brew.text;
@@ -123,7 +120,7 @@ app.get('/source/:id', asyncHandler(async (req, res)=>{
//Download brew source page //Download brew source page
app.get('/download/:id', asyncHandler(async (req, res)=>{ app.get('/download/:id', asyncHandler(async (req, res)=>{
const brew = await getBrewFromId(req.params.id, 'share'); const brew = await getBrewFromId(req.params.id, 'raw');
const prefix = 'HB - '; const prefix = 'HB - ';
let fileName = sanitizeFilename(`${prefix}${brew.title}`).replaceAll(' ', ''); let fileName = sanitizeFilename(`${prefix}${brew.title}`).replaceAll(' ', '');

View File

@@ -20,10 +20,12 @@ const getGoodBrewTitle = (text)=>{
}; };
const mergeBrewText = (text, style)=>{ const mergeBrewText = (text, style)=>{
if(typeof style !== 'undefined') {
text = `\`\`\`css\n` + text = `\`\`\`css\n` +
`${style}\n` + `${style}\n` +
`\`\`\`\n\n` + `\`\`\`\n\n` +
`${text}`; `${text}`;
}
return text; return text;
}; };

View File

@@ -56,7 +56,7 @@ HomebrewSchema.statics.getByUser = function(username, allowAccess=false){
if(allowAccess){ if(allowAccess){
delete query.published; delete query.published;
} }
Homebrew.find(query, (err, brews)=>{ Homebrew.find(query).lean().exec((err, brews)=>{ //lean() converts results to JSObjects
if(err) return reject('Can not find brew'); if(err) return reject('Can not find brew');
return resolve(brews); return resolve(brews);
}); });

View File

@@ -17,7 +17,7 @@ const Nav = {
} }
}), }),
logo : function(){ logo : function(){
return <a className='navLogo' href='http://naturalcrit.com'> return <a className='navLogo' href='https://www.naturalcrit.com'>
<NaturalCritIcon /> <NaturalCritIcon />
<span className='name'> <span className='name'>
Natural<span className='crit'>Crit</span> Natural<span className='crit'>Crit</span>