mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-11-04 20:29:01 +00:00
Merge branch 'master' into fix-codemirror
This commit is contained in:
+78
-135
@@ -2,7 +2,6 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { model as HomebrewModel } from './homebrew.model.js';
|
import { model as HomebrewModel } from './homebrew.model.js';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import zlib from 'zlib';
|
|
||||||
import GoogleActions from './googleActions.js';
|
import GoogleActions from './googleActions.js';
|
||||||
import { hbfm } from 'marked-hbfm';
|
import { hbfm } from 'marked-hbfm';
|
||||||
import * as yaml from 'js-yaml';
|
import * as yaml from 'js-yaml';
|
||||||
@@ -27,17 +26,8 @@ const isStaticTheme = (renderer, themeName)=>{
|
|||||||
return Themes[renderer]?.[themeName] !== undefined;
|
return Themes[renderer]?.[themeName] !== undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
// const getTopBrews = (cb) => {
|
|
||||||
// HomebrewModel.find().sort({ views: -1 }).limit(5).exec(function(err, brews) {
|
|
||||||
// cb(brews);
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
|
|
||||||
|
|
||||||
const migrateSystemsToTags = (brew)=>{
|
const migrateSystemsToTags = (brew)=>{
|
||||||
if(!('systems' in brew)) return brew;
|
if(!('systems' in brew) || !Array.isArray(brew.systems) || brew.systems.length === 0) {
|
||||||
|
|
||||||
if(!Array.isArray(brew.systems) || brew.systems.length === 0) {
|
|
||||||
brew.systems = undefined;
|
brew.systems = undefined;
|
||||||
return brew;
|
return brew;
|
||||||
}
|
}
|
||||||
@@ -108,19 +98,17 @@ const api = {
|
|||||||
|
|
||||||
const brews = await HomebrewModel.getByUser(username, true, fields, { tags: { $in: ['meta:theme', 'meta:Theme'] } });
|
const brews = await HomebrewModel.getByUser(username, true, fields, { tags: { $in: ['meta:theme', 'meta:Theme'] } });
|
||||||
|
|
||||||
if(brews) {
|
for (const brew of brews) {
|
||||||
for (const brew of brews) {
|
userThemes[brew.renderer] ??= {};
|
||||||
userThemes[brew.renderer] ??= {};
|
userThemes[brew.renderer][brew.shareId] = {
|
||||||
userThemes[brew.renderer][brew.shareId] = {
|
name : brew.title,
|
||||||
name : brew.title,
|
renderer : brew.renderer,
|
||||||
renderer : brew.renderer,
|
baseTheme : brew.theme,
|
||||||
baseTheme : brew.theme,
|
baseSnippets : false,
|
||||||
baseSnippets : false,
|
author : brew.authors[0],
|
||||||
author : brew.authors[0],
|
path : brew.shareId,
|
||||||
path : brew.shareId,
|
thumbnail : brew.thumbnail || '/assets/naturalCritLogoWhite.svg'
|
||||||
thumbnail : brew.thumbnail || '/assets/naturalCritLogoWhite.svg'
|
};
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return userThemes;
|
return userThemes;
|
||||||
@@ -189,18 +177,14 @@ const api = {
|
|||||||
stub.renderer = stub.renderer || undefined; // Clear empty strings
|
stub.renderer = stub.renderer || undefined; // Clear empty strings
|
||||||
stub = _.defaults(stub, DEFAULT_BREW_LOAD); // Fill in blank fields
|
stub = _.defaults(stub, DEFAULT_BREW_LOAD); // Fill in blank fields
|
||||||
|
|
||||||
|
req.brew = migrateSystemsToTags(stub);
|
||||||
|
|
||||||
const fixedStub = migrateSystemsToTags(stub);
|
|
||||||
req.brew = fixedStub;
|
|
||||||
splitTextStyleAndMetadata(req.brew);
|
splitTextStyleAndMetadata(req.brew);
|
||||||
next();
|
next();
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getCSS : async (req, res)=>{
|
getCSS : async (req, res)=>{
|
||||||
const { brew } = req;
|
const { brew } = req;
|
||||||
if(!brew) return res.status(404).send('');
|
if(!brew?.style) return res.status(404).send('');
|
||||||
if(!brew.style) return res.status(404).send('');
|
|
||||||
|
|
||||||
res.set({
|
res.set({
|
||||||
'Cache-Control' : 'no-cache',
|
'Cache-Control' : 'no-cache',
|
||||||
@@ -216,19 +200,15 @@ const api = {
|
|||||||
`\`\`\`\n\n` +
|
`\`\`\`\n\n` +
|
||||||
`${text}`;
|
`${text}`;
|
||||||
}
|
}
|
||||||
const metadata = _.pick(brew, ['title', 'description', 'tags', 'renderer', 'theme']);
|
const metadata = _.pick(brew, ['title', 'description', 'tags', 'renderer', 'theme', 'columns', 'columnGutter', 'license', 'legalAuthors']);
|
||||||
const snippetsArray = brewSnippetsToJSON('brew_snippets', brew.snippets, null, false).snippets;
|
const snippetsArray = brewSnippetsToJSON('brew_snippets', brew.snippets, null, false).snippets;
|
||||||
metadata.snippets = snippetsArray.length > 0 ? snippetsArray : undefined;
|
metadata.snippets = snippetsArray.length > 0 ? snippetsArray : undefined;
|
||||||
metadata.bleedSize = { top: brew?.bleedSize?.top, bottom: brew?.bleedSize?.bottom, inner: brew?.bleedSize?.inner, outer: brew?.bleedSize?.outer };
|
metadata.bleedSize = { top: brew?.bleedSize?.top, bottom: brew?.bleedSize?.bottom, inner: brew?.bleedSize?.inner, outer: brew?.bleedSize?.outer };
|
||||||
metadata.safetySpace = { top: brew?.safetySpace?.top, bottom: brew?.safetySpace?.bottom, outer: brew?.safetySpace?.outer, inner: brew?.safetySpace?.inner };
|
metadata.safetySpace = { top: brew?.safetySpace?.top, bottom: brew?.safetySpace?.bottom, outer: brew?.safetySpace?.outer, inner: brew?.safetySpace?.inner };
|
||||||
metadata.trimSize = { width: brew?.trimSize?.width, height: brew?.trimSize?.height };
|
metadata.trimSize = { width: brew?.trimSize?.width, height: brew?.trimSize?.height };
|
||||||
metadata.columns = brew?.columns;
|
|
||||||
metadata.columnGutter = brew?.columnGutter;
|
|
||||||
metadata.license = brew?.license;
|
|
||||||
metadata.legalAuthors = brew?.legalAuthors;
|
|
||||||
|
|
||||||
text = `\`\`\`metadata\n` +
|
text = `\`\`\`metadata\n` +
|
||||||
`${yaml.dump(metadata)}\n` +
|
`${yaml.dump(metadata)}` +
|
||||||
`\`\`\`\n\n` +
|
`\`\`\`\n\n` +
|
||||||
`${text}`;
|
`${text}`;
|
||||||
return text;
|
return text;
|
||||||
@@ -238,28 +218,14 @@ const api = {
|
|||||||
return (tokens.find((token)=>token.type === 'heading' || token.type === 'paragraph')?.text || 'No Title')
|
return (tokens.find((token)=>token.type === 'heading' || token.type === 'paragraph')?.text || 'No Title')
|
||||||
.slice(0, MAX_TITLE_LENGTH);
|
.slice(0, MAX_TITLE_LENGTH);
|
||||||
},
|
},
|
||||||
excludePropsFromUpdate : (brew)=>{
|
excludePropsFromUpdate : (brew)=>{ //Remove props that should not update/overwrite when editing
|
||||||
// Remove undesired properties
|
return _.omit(brew, ['_id', 'views', 'lastViewed']);
|
||||||
const modified = _.clone(brew);
|
|
||||||
const propsToExclude = ['_id', 'views', 'lastViewed'];
|
|
||||||
for (const prop of propsToExclude) {
|
|
||||||
delete modified[prop];
|
|
||||||
}
|
|
||||||
return modified;
|
|
||||||
},
|
},
|
||||||
excludeGoogleProps : (brew)=>{
|
excludeGoogleProps : (brew)=>{ //Remove props that should not be saved to Google (only stored to Homebrewery stub)
|
||||||
const modified = _.clone(brew);
|
return _.omit(brew, ['version', 'tags', 'systems', 'published', 'authors', 'invitedAuthors', 'owner', 'views', 'thumbnail']);
|
||||||
const propsToExclude = ['version', 'tags', 'systems', 'published', 'authors', 'owner', 'views', 'thumbnail'];
|
|
||||||
for (const prop of propsToExclude) {
|
|
||||||
delete modified[prop];
|
|
||||||
}
|
|
||||||
return modified;
|
|
||||||
},
|
},
|
||||||
excludeStubProps : (brew)=>{
|
excludeStubProps : (brew)=>{ //Remove props that should not be saved to stub-only brews
|
||||||
const propsToExclude = ['text', 'textBin'];
|
brew.text = brew.textBin = undefined; // Can't use _.omit because this brew is a Mongoose object
|
||||||
for (const prop of propsToExclude) {
|
|
||||||
brew[prop] = undefined;
|
|
||||||
}
|
|
||||||
return brew;
|
return brew;
|
||||||
},
|
},
|
||||||
beforeNewSave : (account, brew)=>{
|
beforeNewSave : (account, brew)=>{
|
||||||
@@ -278,9 +244,7 @@ const api = {
|
|||||||
newGoogleBrew : async (account, brew, res)=>{
|
newGoogleBrew : async (account, brew, res)=>{
|
||||||
const oAuth2Client = GoogleActions.authCheck(account, res);
|
const oAuth2Client = GoogleActions.authCheck(account, res);
|
||||||
|
|
||||||
const newBrew = api.excludeGoogleProps(brew);
|
return await GoogleActions.newGoogleBrew(oAuth2Client, api.excludeGoogleProps(brew));
|
||||||
|
|
||||||
return await GoogleActions.newGoogleBrew(oAuth2Client, newBrew);
|
|
||||||
},
|
},
|
||||||
newBrew : async (req, res)=>{
|
newBrew : async (req, res)=>{
|
||||||
const brew = req.body;
|
const brew = req.body;
|
||||||
@@ -292,7 +256,7 @@ const api = {
|
|||||||
|
|
||||||
api.beforeNewSave(req.account, brew);
|
api.beforeNewSave(req.account, brew);
|
||||||
|
|
||||||
const newHomebrew = new HomebrewModel(brew);
|
let newHomebrew = new HomebrewModel(brew);
|
||||||
newHomebrew.editId = nanoid(12);
|
newHomebrew.editId = nanoid(12);
|
||||||
newHomebrew.shareId = nanoid(12);
|
newHomebrew.shareId = nanoid(12);
|
||||||
|
|
||||||
@@ -301,15 +265,10 @@ const api = {
|
|||||||
googleId = await api.newGoogleBrew(req.account, newHomebrew, res);
|
googleId = await api.newGoogleBrew(req.account, newHomebrew, res);
|
||||||
|
|
||||||
if(!googleId) return;
|
if(!googleId) return;
|
||||||
api.excludeStubProps(newHomebrew);
|
newHomebrew = api.excludeStubProps(newHomebrew);
|
||||||
newHomebrew.googleId = googleId;
|
newHomebrew.googleId = googleId;
|
||||||
} else {
|
|
||||||
// Compress brew text to binary before saving
|
|
||||||
newHomebrew.textBin = zlib.deflateRawSync(newHomebrew.text);
|
|
||||||
// Delete the non-binary text field since it's not needed anymore
|
|
||||||
newHomebrew.text = undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
saved = await newHomebrew.save()
|
saved = await newHomebrew.save()
|
||||||
.catch((err)=>{
|
.catch((err)=>{
|
||||||
console.error(err, err.toString(), err.stack);
|
console.error(err, err.toString(), err.stack);
|
||||||
@@ -380,7 +339,6 @@ const api = {
|
|||||||
return res.status(200).send(returnObj);
|
return res.status(200).send(returnObj);
|
||||||
},
|
},
|
||||||
updateBrew : async (req, res)=>{
|
updateBrew : async (req, res)=>{
|
||||||
// Initialize brew from request and body, destructure query params, and set the initial value for the after-save method
|
|
||||||
const brewFromClient = api.excludePropsFromUpdate(req.body);
|
const brewFromClient = api.excludePropsFromUpdate(req.body);
|
||||||
const brewFromServer = req.brew;
|
const brewFromServer = req.brew;
|
||||||
|
|
||||||
@@ -406,16 +364,17 @@ const api = {
|
|||||||
const patches = parsePatch(brewFromClient.patches);
|
const patches = parsePatch(brewFromClient.patches);
|
||||||
// Patch to a throwaway variable while parallelizing - we're more concerned with error/no error.
|
// Patch to a throwaway variable while parallelizing - we're more concerned with error/no error.
|
||||||
result = applyPatches(patches, encodeURI(brewFromServer.text));
|
result = applyPatches(patches, encodeURI(brewFromServer.text));
|
||||||
const failedPatches = patches.map((patch, index)=>{if(!result[1][index]){ return patch; }});
|
const failedPatchCount = result[1].filter((patchApplied)=>!patchApplied).length; //Count how many patches failed to apply
|
||||||
if(failedPatches > 0){
|
if(failedPatchCount){
|
||||||
throw (`Patch failure: ${failedPatches}/${result[1].length} did not apply`);
|
throw (`Patch failure: ${failedPatchCount}/${result[1].length} did not apply`);
|
||||||
}
|
}
|
||||||
if(decodeURI(result[0]) != brewFromClient.text){
|
patchedText = decodeURI(result[0]);
|
||||||
|
if(patchedText != brewFromClient.text){
|
||||||
|
debugTextMismatch(brewFromClient.text, patchedText, `edit/${brewFromClient.editId}`);
|
||||||
throw ('Patches did not apply cleanly, text mismatch detected');
|
throw ('Patches did not apply cleanly, text mismatch detected');
|
||||||
}
|
}
|
||||||
// brew.text = applyPatches(patches, brewFromServer.text)[0];
|
// brew.text = applyPatches(patches, brewFromServer.text)[0];
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
debugTextMismatch(brewFromClient.text, brewFromServer.text, `edit/${brewFromClient.editId}`);
|
|
||||||
console.error('Failed to apply patches:', {
|
console.error('Failed to apply patches:', {
|
||||||
// patches : brewFromClient.patches,
|
// patches : brewFromClient.patches,
|
||||||
// result : result,
|
// result : result,
|
||||||
@@ -426,77 +385,63 @@ const api = {
|
|||||||
// throw err; // rethrow to preserve the 500 behavior
|
// throw err; // rethrow to preserve the 500 behavior
|
||||||
}
|
}
|
||||||
|
|
||||||
let brew = _.assign(brewFromServer, brewFromClient);
|
let brew = _.assign(brewFromServer, brewFromClient);
|
||||||
|
|
||||||
migrateSystemsToTags(brew);
|
|
||||||
|
|
||||||
|
brew = migrateSystemsToTags(brew);
|
||||||
brew.title = brew.title.trim();
|
brew.title = brew.title.trim();
|
||||||
brew.description = brew.description.trim() || '';
|
brew.description = brew.description.trim() || '';
|
||||||
brew.text = api.mergeBrewText(brew);
|
brew.text = api.mergeBrewText(brew);
|
||||||
|
brew.updatedAt = new Date();
|
||||||
const googleId = brew.googleId;
|
brew.version = (brew.version || 1) + 1;
|
||||||
const { saveToGoogle, removeFromGoogle } = req.query;
|
|
||||||
let afterSave = async ()=>true;
|
|
||||||
|
|
||||||
if(brew.googleId && removeFromGoogle) {
|
|
||||||
// If the google id exists and we're removing it from google, set afterSave to delete the google brew and mark the brew's google id as undefined
|
|
||||||
afterSave = async ()=>{
|
|
||||||
return await api.deleteGoogleBrew(req.account, googleId, brew.editId, res)
|
|
||||||
.catch((err)=>{
|
|
||||||
console.error(err);
|
|
||||||
res.status(err?.status || err?.response?.status || 500).send(err.message || err);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
brew.googleId = undefined;
|
|
||||||
} else if(!brew.googleId && saveToGoogle) {
|
|
||||||
// If we don't have a google id and the user wants to save to google, create the google brew and set the google id on the brew
|
|
||||||
brew.googleId = await api.newGoogleBrew(req.account, api.excludeGoogleProps(brew), res);
|
|
||||||
|
|
||||||
if(!brew.googleId) return;
|
|
||||||
} else if(brew.googleId) {
|
|
||||||
// If the google id exists and no other actions are being performed, update the google brew
|
|
||||||
const updated = await GoogleActions.updateGoogleBrew(api.excludeGoogleProps(brew), req.ip);
|
|
||||||
|
|
||||||
if(!updated) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(brew.googleId) {
|
|
||||||
// If the google id exists after all those actions, exclude the props that are stored in google and aren't needed for rendering the brew items
|
|
||||||
api.excludeStubProps(brew);
|
|
||||||
} else {
|
|
||||||
// Compress brew text to binary before saving
|
|
||||||
brew.textBin = zlib.deflateRawSync(brew.text);
|
|
||||||
// Delete the non-binary text field since it's not needed anymore
|
|
||||||
brew.text = undefined;
|
|
||||||
}
|
|
||||||
brew.updatedAt = new Date();
|
|
||||||
brew.version = (brew.version || 1) + 1;
|
|
||||||
|
|
||||||
if(req.account) {
|
if(req.account) {
|
||||||
brew.authors = _.uniq(_.concat(brew.authors, req.account.username));
|
brew.authors = _.uniq(_.concat(brew.authors, req.account.username));
|
||||||
brew.invitedAuthors = _.uniq(_.filter(brew.invitedAuthors, (a)=>req.account.username !== a));
|
brew.invitedAuthors = _.uniq(_.filter(brew.invitedAuthors, (a)=>req.account.username !== a));
|
||||||
}
|
}
|
||||||
|
|
||||||
// define a function to catch our save errors
|
//=====----- Update to or remove from Google Drive -----=========//
|
||||||
const saveError = (err)=>{
|
const originalGoogleId = brew.googleId;
|
||||||
console.error(err);
|
const { saveToGoogle, removeFromGoogle } = req.query;
|
||||||
res.status(err.status || 500).send(err.message || 'Unable to save brew to Homebrewery database');
|
|
||||||
};
|
if(brew.googleId && removeFromGoogle) { // If removing from google, remove the brew's googleId
|
||||||
let saved;
|
brew.googleId = undefined;
|
||||||
if(!brew._id) {
|
|
||||||
// if the brew does not have a stub id, create and save it, then write the new value back to the brew.
|
|
||||||
saved = await new HomebrewModel(brew).save().catch(saveError);
|
|
||||||
} else {
|
|
||||||
// if the brew does have a stub id, update it using the stub id as the key.
|
|
||||||
brew = _.assign(await HomebrewModel.findOne({ _id: brew._id }), brew);
|
|
||||||
saved = await brew.save()
|
|
||||||
.catch(saveError);
|
|
||||||
}
|
}
|
||||||
|
else if(!brew.googleId && saveToGoogle) { // If adding to google, create new google document and record the googleId
|
||||||
|
brew.googleId = await api.newGoogleBrew(req.account, brew, res);
|
||||||
|
if(!brew.googleId) return;
|
||||||
|
}
|
||||||
|
else if(brew.googleId) { // If already on google, update the google brew
|
||||||
|
const updated = await GoogleActions.updateGoogleBrew(api.excludeGoogleProps(brew), req.ip);
|
||||||
|
if(!updated) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=====----- Update to Mongo -----=====//
|
||||||
|
if(brew.googleId) {
|
||||||
|
// If google id exists after above actions, Mongo will store only a stub; exclude non-stub properties from update
|
||||||
|
brew = api.excludeStubProps(brew);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(brew._id) // if the brew has a stub id, fetch and merge into Mongo stub document
|
||||||
|
brew = _.assign(await HomebrewModel.findOne({ _id: brew._id }), brew);
|
||||||
|
else // if not, create a new Mongo document
|
||||||
|
brew = new HomebrewModel(brew);
|
||||||
|
|
||||||
|
const saved = await brew.save()
|
||||||
|
.catch((err)=>{
|
||||||
|
console.error(err);
|
||||||
|
res.status(err.status || 500).send(err.message || 'Unable to save brew to Homebrewery database');
|
||||||
|
});
|
||||||
|
|
||||||
if(!saved) return;
|
if(!saved) return;
|
||||||
// Call and wait for afterSave to complete
|
|
||||||
const after = await afterSave();
|
if(originalGoogleId && removeFromGoogle) {
|
||||||
if(!after) return;
|
const deleted = await api.deleteGoogleBrew(req.account, originalGoogleId, brew.editId, res)
|
||||||
|
.catch((err)=>{
|
||||||
|
console.error(err);
|
||||||
|
res.status(err?.status || err?.response?.status || 500).send(err.message || err);
|
||||||
|
});
|
||||||
|
|
||||||
|
if(!deleted) return;
|
||||||
|
}
|
||||||
|
|
||||||
saved.textBin = undefined; // Remove textBin from the saved object to save bandwidth
|
saved.textBin = undefined; // Remove textBin from the saved object to save bandwidth
|
||||||
|
|
||||||
@@ -549,8 +494,6 @@ const api = {
|
|||||||
if(shouldDeleteGoogleBrew) {
|
if(shouldDeleteGoogleBrew) {
|
||||||
// When there are still authors remaining, we delete the google brew but store the full brew in the Homebrewery database
|
// When there are still authors remaining, we delete the google brew but store the full brew in the Homebrewery database
|
||||||
brew.googleId = undefined;
|
brew.googleId = undefined;
|
||||||
brew.textBin = zlib.deflateRawSync(brew.text);
|
|
||||||
brew.text = undefined;
|
|
||||||
}
|
}
|
||||||
brew.markModified('authors'); //Mongo will not properly update arrays without markModified()
|
brew.markModified('authors'); //Mongo will not properly update arrays without markModified()
|
||||||
await brew.save()
|
await brew.save()
|
||||||
|
|||||||
+70
-63
@@ -1,6 +1,7 @@
|
|||||||
/* eslint-disable max-lines */
|
/* eslint-disable max-lines */
|
||||||
|
|
||||||
import { splitTextStyleAndMetadata } from '../shared/helpers.js';
|
import { splitTextStyleAndMetadata } from '../shared/helpers.js';
|
||||||
|
import dedent from 'dedent';
|
||||||
|
|
||||||
describe('Tests for api', ()=>{
|
describe('Tests for api', ()=>{
|
||||||
let api;
|
let api;
|
||||||
@@ -493,35 +494,35 @@ describe('Tests for api', ()=>{
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result).toEqual(`\`\`\`metadata
|
expect(result).toEqual(dedent`
|
||||||
title: some title
|
\`\`\`metadata
|
||||||
description: this is a description
|
title: some title
|
||||||
tags:
|
description: this is a description
|
||||||
- something
|
tags:
|
||||||
- fun
|
- something
|
||||||
renderer: v3
|
- fun
|
||||||
theme: phb
|
renderer: v3
|
||||||
bleedSize:
|
theme: phb
|
||||||
top: .125in
|
columns: '2'
|
||||||
bottom: .125in
|
columnGutter: .125in
|
||||||
inner: .125in
|
license: None
|
||||||
outer: .125in
|
legalAuthors: ''
|
||||||
safetySpace:
|
bleedSize:
|
||||||
top: .25in
|
top: .125in
|
||||||
bottom: .25in
|
bottom: .125in
|
||||||
outer: .25in
|
inner: .125in
|
||||||
inner: .5in
|
outer: .125in
|
||||||
trimSize:
|
safetySpace:
|
||||||
width: 8.5in
|
top: .25in
|
||||||
height: 11in
|
bottom: .25in
|
||||||
columns: '2'
|
outer: .25in
|
||||||
columnGutter: .125in
|
inner: .5in
|
||||||
license: None
|
trimSize:
|
||||||
legalAuthors: ''
|
width: 8.5in
|
||||||
|
height: 11in
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
\`\`\`
|
brew`);
|
||||||
|
|
||||||
brew`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set metadata and style', ()=>{
|
it('should set metadata and style', ()=>{
|
||||||
@@ -556,39 +557,39 @@ brew`);
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result).toEqual(`\`\`\`metadata
|
expect(result).toEqual(dedent`
|
||||||
title: some title
|
\`\`\`metadata
|
||||||
description: this is a description
|
title: some title
|
||||||
tags:
|
description: this is a description
|
||||||
- something
|
tags:
|
||||||
- fun
|
- something
|
||||||
renderer: v3
|
- fun
|
||||||
theme: phb
|
renderer: v3
|
||||||
bleedSize:
|
theme: phb
|
||||||
top: .125in
|
columns: '2'
|
||||||
bottom: .125in
|
columnGutter: .125in
|
||||||
inner: .125in
|
license: None
|
||||||
outer: .125in
|
legalAuthors: ''
|
||||||
safetySpace:
|
bleedSize:
|
||||||
top: .25in
|
top: .125in
|
||||||
bottom: .25in
|
bottom: .125in
|
||||||
outer: .25in
|
inner: .125in
|
||||||
inner: .5in
|
outer: .125in
|
||||||
trimSize:
|
safetySpace:
|
||||||
width: 8.5in
|
top: .25in
|
||||||
height: 11in
|
bottom: .25in
|
||||||
columns: '2'
|
outer: .25in
|
||||||
columnGutter: .125in
|
inner: .5in
|
||||||
license: None
|
trimSize:
|
||||||
legalAuthors: ''
|
width: 8.5in
|
||||||
|
height: 11in
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
\`\`\`
|
\`\`\`css
|
||||||
|
hello yes i am css
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
\`\`\`css
|
brew`);
|
||||||
hello yes i am css
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
brew`);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('exclusion methods', ()=>{
|
describe('exclusion methods', ()=>{
|
||||||
@@ -700,8 +701,15 @@ brew`);
|
|||||||
shareId : expect.any(String),
|
shareId : expect.any(String),
|
||||||
style : undefined,
|
style : undefined,
|
||||||
tags : [],
|
tags : [],
|
||||||
text : undefined,
|
text : '```metadata\n' +
|
||||||
textBin : expect.objectContaining({}),
|
'title: asdf\n' +
|
||||||
|
'bleedSize: {}\n' +
|
||||||
|
'safetySpace: {}\n' +
|
||||||
|
'trimSize: {}' +
|
||||||
|
'\n' +
|
||||||
|
'```\n' +
|
||||||
|
'\n' +
|
||||||
|
'asdf',
|
||||||
theme : '5ePHB',
|
theme : '5ePHB',
|
||||||
thumbnail : '',
|
thumbnail : '',
|
||||||
title : 'asdf',
|
title : 'asdf',
|
||||||
@@ -1233,8 +1241,7 @@ brew`);
|
|||||||
expect(saveFunc).toHaveBeenCalled();
|
expect(saveFunc).toHaveBeenCalled();
|
||||||
expect(saved.authors).toEqual(['test2']);
|
expect(saved.authors).toEqual(['test2']);
|
||||||
expect(saved.googleId).toEqual(undefined);
|
expect(saved.googleId).toEqual(undefined);
|
||||||
expect(saved.text).toEqual(undefined);
|
expect(saved.text).not.toEqual(undefined);
|
||||||
expect(saved.textBin).not.toEqual(undefined);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should retain google brew and update stub when multiple authors and extra author requests deletion', async ()=>{
|
it('should retain google brew and update stub when multiple authors and extra author requests deletion', async ()=>{
|
||||||
|
|||||||
@@ -32,14 +32,21 @@ const HomebrewSchema = mongoose.Schema({
|
|||||||
lock : { type: Object, index: true }
|
lock : { type: Object, index: true }
|
||||||
}, { versionKey: false });
|
}, { versionKey: false });
|
||||||
|
|
||||||
|
HomebrewSchema.pre('save', function() {
|
||||||
|
if(this.text !== undefined) {
|
||||||
|
this.textBin = zlib.deflateRawSync(this.text);
|
||||||
|
this.text = undefined;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
HomebrewSchema.statics.increaseView = async function(query) {
|
HomebrewSchema.statics.increaseView = async function(query) {
|
||||||
const brew = await Homebrew.findOne(query).exec();
|
const brew = await Homebrew.findOne(query).exec();
|
||||||
brew.lastViewed = new Date();
|
brew.lastViewed = new Date();
|
||||||
brew.views = brew.views + 1;
|
brew.views = brew.views + 1;
|
||||||
await brew.save()
|
await brew.save()
|
||||||
.catch((err)=>{
|
.catch((err)=>{
|
||||||
return err;
|
return err;
|
||||||
});
|
});
|
||||||
return brew;
|
return brew;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -51,6 +58,7 @@ HomebrewSchema.statics.get = async function(query, fields=null){
|
|||||||
if(!_.isNil(brew.textBin)) { // Uncompress zipped text field
|
if(!_.isNil(brew.textBin)) { // Uncompress zipped text field
|
||||||
const unzipped = zlib.inflateRawSync(brew.textBin);
|
const unzipped = zlib.inflateRawSync(brew.textBin);
|
||||||
brew.text = unzipped.toString();
|
brew.text = unzipped.toString();
|
||||||
|
brew.textBin = undefined;
|
||||||
}
|
}
|
||||||
return brew;
|
return brew;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user