diff --git a/client/homebrew/navbar/print.navitem.jsx b/client/homebrew/navbar/print.navitem.jsx index ff2d75d67..b500c24d6 100644 --- a/client/homebrew/navbar/print.navitem.jsx +++ b/client/homebrew/navbar/print.navitem.jsx @@ -2,7 +2,12 @@ import React, { useState, useEffect } from 'react'; import Nav from './nav.jsx'; import { printCurrentBrew } from '@shared/helpers.js'; -export default function(){ +const processShareId = (brew)=>{ + + return brew.googleId && !brew.stubbed ? brew.googleId + brew.shareId : brew.shareId; +}; + +export default ({ currentBrew })=>{ const [printing, setPrinting] = useState(false); // listen for print cycle events to display "loading" message since it can take some time. @@ -19,7 +24,27 @@ export default function(){ const handlePrintPrepFinished = ()=>{ setPrinting(false); }; - return + if(currentBrew?.shareId) return + + export + + + {printing ? 'loading' : 'get PDF'} + + + Markdown + + + Markdown (TOML) + + + Markdown (JSON) + + + Markdown (Homebrewery) + + ; + else return {printing ? 'loading' : 'get PDF'} ; }; diff --git a/client/homebrew/pages/basePages/editPage/editorPage.jsx b/client/homebrew/pages/basePages/editPage/editorPage.jsx index b9fb34597..718aab442 100644 --- a/client/homebrew/pages/basePages/editPage/editorPage.jsx +++ b/client/homebrew/pages/basePages/editPage/editorPage.jsx @@ -372,7 +372,7 @@ const EditorPage = (props)=>{ {(pageName == 'editPage') && renderAutoSaveButton()} } - + {(pageName == 'editPage') && } diff --git a/client/homebrew/pages/sharePage/sharePage.jsx b/client/homebrew/pages/sharePage/sharePage.jsx index 002844c2c..42a9c4241 100644 --- a/client/homebrew/pages/sharePage/sharePage.jsx +++ b/client/homebrew/pages/sharePage/sharePage.jsx @@ -117,7 +117,7 @@ const SharePage = (props)=>{ view {renderEditLink()} - + download diff --git a/server/homebrew.api.js b/server/homebrew.api.js index aa1f1f84a..8702ec42b 100644 --- a/server/homebrew.api.js +++ b/server/homebrew.api.js @@ -10,7 +10,7 @@ import asyncHandler from 'express-async-handler'; import { nanoid } from 'nanoid'; import { makePatches, applyPatches, stringifyPatches, parsePatch } from '@sanity/diff-match-patch'; import { md5 } from 'hash-wasm'; -import { splitTextStyleAndMetadata, +import { splitTextStyleAndMetadata, transformFrontmatter, brewSnippetsToJSON, debugTextMismatch } from '../shared/helpers.js'; import checkClientVersion from './middleware/check-client-version.js'; import dbCheck from './middleware/dbCheck.js'; @@ -209,29 +209,7 @@ const api = { return res.status(200).send(brew.style); }, mergeBrewText : (brew)=>{ - let text = brew.text; - if(brew.style !== undefined) { - text = `\`\`\`css\n` + - `${brew.style || ''}\n` + - `\`\`\`\n\n` + - `${text}`; - } - const metadata = _.pick(brew, ['title', 'description', 'tags', 'renderer', 'theme']); - const snippetsArray = brewSnippetsToJSON('brew_snippets', brew.snippets, null, false).snippets; - 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.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.columns = brew?.columns; - metadata.columnGutter = brew?.columnGutter; - metadata.license = brew?.license; - metadata.legalAuthors = brew?.legalAuthors; - - text = `\`\`\`metadata\n` + - `${yaml.dump(metadata)}\n` + - `\`\`\`\n\n` + - `${text}`; - return text; + return transformFrontmatter(brew); }, getGoodBrewTitle : (text)=>{ const tokens = hbfm.marked.lexer(text); diff --git a/server/homebrew.api.spec.js b/server/homebrew.api.spec.js index 8bda5407b..b4337e6fc 100644 --- a/server/homebrew.api.spec.js +++ b/server/homebrew.api.spec.js @@ -499,8 +499,6 @@ description: this is a description tags: - something - fun -renderer: v3 -theme: phb bleedSize: top: .125in bottom: .125in @@ -518,6 +516,8 @@ columns: '2' columnGutter: .125in license: None legalAuthors: '' +renderer: v3 +theme: phb \`\`\` @@ -554,7 +554,7 @@ brew`); width : '8.5in', height : '11in', }, - }); + }, 'hb'); expect(result).toEqual(`\`\`\`metadata title: some title @@ -562,8 +562,6 @@ description: this is a description tags: - something - fun -renderer: v3 -theme: phb bleedSize: top: .125in bottom: .125in @@ -581,6 +579,8 @@ columns: '2' columnGutter: .125in license: None legalAuthors: '' +renderer: v3 +theme: phb \`\`\` diff --git a/server/page-routes.js b/server/page-routes.js index 85436d2bc..49879391e 100644 --- a/server/page-routes.js +++ b/server/page-routes.js @@ -15,7 +15,7 @@ import fs from 'fs'; import dbCheck from './middleware/dbCheck.js'; import sanitizeFilename from 'sanitize-filename'; import { DEFAULT_BREW } from './brewDefaults.js'; -import { splitTextStyleAndMetadata } from '../shared/helpers.js'; +import { splitTextStyleAndMetadata, transformFrontmatter } from '../shared/helpers.js'; import GoogleActions from './googleActions.js'; import api from './homebrew.api.js'; @@ -135,9 +135,19 @@ export default function pageRoutes({ }); //Download brew source page - app.get('/download/:id', asyncHandler(getBrew('share')), (req, res)=>{ + app.get('/download/:format/:id', asyncHandler(getBrew('share')), async (req, res)=>{ + const markdownFormats = { + hb : 'homebrewery', + cm : 'commonmark', + toml : 'toml', + json : 'json' + }; + const { brew } = req; + + const lastBrew = brew.text; sanitizeBrew(brew, 'share'); + brew.text = await transformFrontmatter(brew, req.params.format); const prefix = 'HB - '; const encodeRFC3986ValueChars = (str)=>{ @@ -152,7 +162,7 @@ export default function pageRoutes({ res.set({ 'Cache-Control' : 'no-cache', 'Content-Type' : 'text/plain', - 'Content-Disposition' : `attachment; filename*=UTF-8''${encodeRFC3986ValueChars(fileName)}.txt` + 'Content-Disposition' : `attachment; filename*=UTF-8''${encodeRFC3986ValueChars(fileName)}.${markdownFormats[req.params.format]}.md` }); res.status(200).send(brew.text); }); diff --git a/shared/helpers.js b/shared/helpers.js index d20687843..6d8180ae1 100644 --- a/shared/helpers.js +++ b/shared/helpers.js @@ -114,6 +114,44 @@ const splitTextStyleAndMetadata = (brew)=>{ if(typeof brew.tags === 'string') brew.tags = brew.tags ? [brew.tags] : []; }; +const transformFrontmatter = (brew, format = 'hb')=>{ + const markdownFormats = { + hb : '```metadata', + cm : '---', + toml : '+++', + json : ';;;' + }; + + let text = brew.text; + if((brew.style !== undefined) && (format == 'hb')) { + text = `\`\`\`css\n` + + `${brew.style || ''}\n` + + `\`\`\`\n\n` + + `${text}`; + } + const metadata = _.pick(brew, ['title', 'description', 'tags']); + if(format == 'hb') { + const snippetsArray = brewSnippetsToJSON('brew_snippets', brew.snippets, null, false).snippets; + 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.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.columns = brew?.columns; + metadata.columnGutter = brew?.columnGutter; + metadata.license = brew?.license; + metadata.legalAuthors = brew?.legalAuthors; + metadata.renderer = brew.renderer; + metadata.theme = brew.theme; + } + + text = `${markdownFormats[format]}\n` + + `${format != 'json' ? yaml.dump(metadata) : JSON.stringify(metadata)}\n` + + `${markdownFormats[format].slice(0, 3)}\n\n` + + `${text}`; + + return text; +}; + const printCurrentBrew = async ()=>{ if(window.typeof !== 'undefined') { // fire a custom event for the print cycle @@ -230,5 +268,6 @@ export { fetchThemeBundle, brewSnippetsToJSON, debugTextMismatch, - yamlSnippetsToText + yamlSnippetsToText, + transformFrontmatter };