diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index 787423528..a8435cde5 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -1,3 +1,4 @@ +/*eslint max-lines: ["warn", {"max": 300, "skipBlankLines": true, "skipComments": true}]*/ require('./brewRenderer.less'); const React = require('react'); const createClass = require('create-react-class'); @@ -13,6 +14,8 @@ const RenderWarnings = require('homebrewery/renderWarnings/renderWarnings.jsx'); const NotificationPopup = require('./notificationPopup/notificationPopup.jsx'); const Frame = require('react-frame-component').default; +const Themes = require('themes/themes.json'); + const PAGE_HEIGHT = 1056; const PPR_THRESHOLD = 50; @@ -23,6 +26,7 @@ const BrewRenderer = createClass({ text : '', style : '', renderer : 'legacy', + theme : '5ePHB', errors : [] }; }, @@ -177,6 +181,9 @@ const BrewRenderer = createClass({ render : function(){ //render in iFrame so broken code doesn't crash the site. //Also render dummy page while iframe is mounting. + const rendererPath = this.props.renderer == 'V3' ? 'V3' : 'Legacy'; + const themePath = this.props.theme ?? '5ePHB'; + const baseThemePath = Themes[rendererPath][themePath].baseTheme; return ( @@ -200,7 +207,11 @@ const BrewRenderer = createClass({ - + + {baseThemePath && + + } + {/* Apply CSS from Style tab and render pages from Markdown tab */} {this.state.isMounted && diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index fd9f850d3..de3a53a36 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -327,6 +327,7 @@ const Editor = createClass({ onInject={this.handleInject} showEditButtons={this.props.showEditButtons} renderer={this.props.renderer} + theme={this.props.brew.theme} undo={this.undo} redo={this.redo} historySize={this.historySize()} /> diff --git a/client/homebrew/editor/metadataEditor/metadataEditor.jsx b/client/homebrew/editor/metadataEditor/metadataEditor.jsx index 8e56ae9e5..29c193323 100644 --- a/client/homebrew/editor/metadataEditor/metadataEditor.jsx +++ b/client/homebrew/editor/metadataEditor/metadataEditor.jsx @@ -5,8 +5,11 @@ const createClass = require('create-react-class'); const _ = require('lodash'); const cx = require('classnames'); const request = require('superagent'); +const Nav = require('naturalcrit/nav/nav.jsx'); const StringArrayEditor = require('../stringArrayEditor/stringArrayEditor.jsx'); +const Themes = require('themes/themes.json'); + const SYSTEMS = ['5e', '4e', '3.5e', 'Pathfinder']; const homebreweryThumbnail = require('../../thumbnail.png'); @@ -23,7 +26,8 @@ const MetadataEditor = createClass({ published : false, authors : [], systems : [], - renderer : 'legacy' + renderer : 'legacy', + theme : '5ePHB' }, onChange : ()=>{} }; @@ -63,6 +67,8 @@ const MetadataEditor = createClass({ handleRenderer : function(renderer, e){ if(e.target.checked){ this.props.metadata.renderer = renderer; + if(renderer == 'legacy') + this.props.metadata.theme = '5ePHB'; } this.props.onChange(this.props.metadata); }, @@ -73,6 +79,12 @@ const MetadataEditor = createClass({ }); }, + handleTheme : function(theme){ + this.props.metadata.renderer = theme.renderer; + this.props.metadata.theme = theme.path; + this.props.onChange(this.props.metadata); + }, + handleDelete : function(){ if(this.props.metadata.authors && this.props.metadata.authors.length <= 1){ if(!confirm('Are you sure you want to delete this brew? Because you are the only owner of this brew, the document will be deleted permanently.')) return; @@ -139,6 +151,45 @@ const MetadataEditor = createClass({ ; }, + renderThemeDropdown : function(){ + if(!global.enable_themes) return; + + const listThemes = (renderer)=>{ + return _.map(_.values(Themes[renderer]), (theme)=>{ + return
this.handleTheme(theme)} title={''}> + {`${theme.renderer} : ${theme.name}`} + +
; + }); + }; + + const currentTheme = Themes[`${_.upperFirst(this.props.metadata.renderer)}`][this.props.metadata.theme]; + let dropdown; + + if(this.props.metadata.renderer == 'legacy') { + dropdown = + +
+ {`Themes are not supported in the Legacy Renderer`} +
+
; + } else { + dropdown = + +
+ {`${_.upperFirst(currentTheme.renderer)} : ${currentTheme.name}`} +
+ {/*listThemes('Legacy')*/} + {listThemes('V3')} +
; + } + + return
+ + {dropdown} +
; + }, + renderRenderOptions : function(){ if(!global.enable_v3) return; @@ -212,6 +263,8 @@ const MetadataEditor = createClass({ + {this.renderThemeDropdown()} + {this.renderRenderOptions()}
diff --git a/client/homebrew/editor/metadataEditor/metadataEditor.less b/client/homebrew/editor/metadataEditor/metadataEditor.less index fd2c33ac8..96bb4858a 100644 --- a/client/homebrew/editor/metadataEditor/metadataEditor.less +++ b/client/homebrew/editor/metadataEditor/metadataEditor.less @@ -15,7 +15,7 @@ display : inline-block; vertical-align : top; width : 80px; - font-size : 0.7em; + font-size : 11px; font-weight : 800; line-height : 1.8em; text-transform : uppercase; @@ -110,6 +110,56 @@ line-height : 1.5em; } + .themes.field{ + font-size : 13.33px; + .navDropdownContainer { + background-color : white; + width : 100%; + position : relative; + z-index : 500; + &.disabled { + font-style :italic; + font-style : italic; + background-color : darkgray; + color : dimgray; + } + &>div:first-child { + border : 2px solid rgb(118,118,118); + padding : 6px 3px; + background-color : inherit; + i { + float : right; + } + &:hover { + background-color : @blue; + color : white; + } + } + .navDropdown { + box-shadow : 0px 5px 10px rgba(0, 0, 0, 0.3); + position : absolute; + width : 100%; + .item { + padding : 3px 3px; + border-top : 1px solid rgb(118, 118, 118); + position : relative; + overflow : hidden; + background-color : white; + &:hover { + background-color : @blue; + color : white; + } + img { + mask-image : linear-gradient(90deg, transparent, black 20%); + -webkit-mask-image : linear-gradient(90deg, transparent, black 20%); + position : absolute; + left : ~"max(100px, 100% - 300px)"; + top : 0px; + } + } + } + } + } .field .list { display: flex; flex-wrap: wrap; diff --git a/client/homebrew/editor/snippetbar/snippetbar.jsx b/client/homebrew/editor/snippetbar/snippetbar.jsx index 0c6b5cc38..9dbee4280 100644 --- a/client/homebrew/editor/snippetbar/snippetbar.jsx +++ b/client/homebrew/editor/snippetbar/snippetbar.jsx @@ -4,9 +4,16 @@ const createClass = require('create-react-class'); const _ = require('lodash'); const cx = require('classnames'); +//Import all themes -const SnippetsLegacy = require('./snippetsLegacy/snippets.js'); -const SnippetsV3 = require('./snippets/snippets.js'); +const Themes = require('themes/themes.json'); + +const ThemeSnippets = {}; +ThemeSnippets['Legacy_5ePHB'] = require('themes/Legacy/5ePHB/snippets.js'); +ThemeSnippets['V3_5ePHB'] = require('themes/V3/5ePHB/snippets.js'); +ThemeSnippets['V3_5eDMG'] = require('themes/V3/5eDMG/snippets.js'); +ThemeSnippets['V3_Journal'] = require('themes/V3/Journal/snippets.js'); +ThemeSnippets['V3_Blank'] = require('themes/V3/Blank/snippets.js'); const execute = function(val, brew){ if(_.isFunction(val)) return val(brew); @@ -32,21 +39,63 @@ const Snippetbar = createClass({ getInitialState : function() { return { - renderer : this.props.renderer + renderer : this.props.renderer, + snippets : [] }; }, + componentDidMount : async function() { + const rendererPath = this.props.renderer == 'V3' ? 'V3' : 'Legacy'; + const themePath = this.props.theme ?? '5ePHB'; + let snippets = _.cloneDeep(ThemeSnippets[`${rendererPath}_${themePath}`]); + snippets = this.compileSnippets(rendererPath, themePath, snippets); + this.setState({ + snippets : snippets + }); + }, + + componentDidUpdate : async function(prevProps) { + if(prevProps.renderer != this.props.renderer || prevProps.theme != this.props.theme) { + const rendererPath = this.props.renderer == 'V3' ? 'V3' : 'Legacy'; + const themePath = this.props.theme ?? '5ePHB'; + let snippets = _.cloneDeep(ThemeSnippets[`${rendererPath}_${themePath}`]); + snippets = this.compileSnippets(rendererPath, themePath, snippets); + this.setState({ + snippets : snippets + }); + } + }, + + mergeCustomizer : function(valueA, valueB, key) { + if(key == 'snippets') { + const result = _.reverse(_.unionBy(_.reverse(valueB), _.reverse(valueA), 'name')); // Join snippets together, with preference for the current theme over the base theme + return _.filter(result, 'gen'); //Only keep snippets with a 'gen' property. + } + }, + + compileSnippets : function(rendererPath, themePath, snippets) { + let compiledSnippets = snippets; + const baseSnippetsPath = Themes[rendererPath][themePath].baseSnippets; + + const objB = _.keyBy(compiledSnippets, 'groupName'); + + if(baseSnippetsPath) { + const objA = _.keyBy(_.cloneDeep(ThemeSnippets[`${rendererPath}_${baseSnippetsPath}`]), 'groupName'); + compiledSnippets = _.values(_.mergeWith(objA, objB, this.mergeCustomizer)); + compiledSnippets = this.compileSnippets(rendererPath, baseSnippetsPath, _.cloneDeep(compiledSnippets)); + } else { + const objA = _.keyBy(_.cloneDeep(ThemeSnippets[`${rendererPath}_Blank`]), 'groupName'); + compiledSnippets = _.values(_.mergeWith(objA, objB, this.mergeCustomizer)); + } + return compiledSnippets; + }, + handleSnippetClick : function(injectedText){ this.props.onInject(injectedText); }, renderSnippetGroups : function(){ - let snippets = []; - - if(this.props.renderer === 'V3') - snippets = SnippetsV3.filter((snippetGroup)=>snippetGroup.view === this.props.view); - else - snippets = SnippetsLegacy.filter((snippetGroup)=>snippetGroup.view === this.props.view); + const snippets = this.state.snippets.filter((snippetGroup)=>snippetGroup.view === this.props.view); return _.map(snippets, (snippetGroup)=>{ return - + {this.props.navItems}
diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index d28968df7..773bf8248 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -418,7 +418,7 @@ const EditPage = createClass({ onMetaChange={this.handleMetaChange} renderer={this.state.brew.renderer} /> - +
; diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index 14ec1c852..251f169c9 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -31,7 +31,8 @@ const NewPage = createClass({ style : undefined, title : '', description : '', - renderer : 'V3' + renderer : 'V3', + theme : '5ePHB' } }; }, @@ -45,7 +46,8 @@ const NewPage = createClass({ style : brew.style ?? undefined, title : brew.title ?? '', description : brew.description ?? '', - renderer : brew.renderer ?? 'legacy' + renderer : brew.renderer ?? 'legacy', + theme : brew.theme ?? '5ePHB' }; } @@ -73,6 +75,7 @@ const NewPage = createClass({ // brew.title = metaStorage?.title || this.state.brew.title; // brew.description = metaStorage?.description || this.state.brew.description; brew.renderer = metaStorage?.renderer ?? brew.renderer; + brew.theme = metaStorage?.theme ?? brew.theme; this.setState({ brew : brew @@ -81,7 +84,7 @@ const NewPage = createClass({ localStorage.setItem(BREWKEY, brew.text); localStorage.setItem(STYLEKEY, brew.style); - localStorage.setItem(METAKEY, JSON.stringify({ 'renderer': brew.renderer })); + localStorage.setItem(METAKEY, JSON.stringify({ 'renderer': brew.renderer, 'theme': brew.theme })); }, componentWillUnmount : function() { document.removeEventListener('keydown', this.handleControlKeys); @@ -129,7 +132,8 @@ const NewPage = createClass({ localStorage.setItem(METAKEY, JSON.stringify({ // 'title' : this.state.brew.title, // 'description' : this.state.brew.description, - 'renderer' : this.state.brew.renderer + 'renderer' : this.state.brew.renderer, + 'theme' : this.state.brew.theme })); }, @@ -287,7 +291,7 @@ const NewPage = createClass({ onMetaChange={this.handleMetaChange} renderer={this.state.brew.renderer} /> - + ; diff --git a/client/homebrew/pages/printPage/printPage.jsx b/client/homebrew/pages/printPage/printPage.jsx index e479fd95b..4390570b3 100644 --- a/client/homebrew/pages/printPage/printPage.jsx +++ b/client/homebrew/pages/printPage/printPage.jsx @@ -7,6 +7,8 @@ const { Meta } = require('vitreum/headtags'); const MarkdownLegacy = require('naturalcrit/markdownLegacy.js'); const Markdown = require('naturalcrit/markdown.js'); +const Themes = require('themes/themes.json'); + const BREWKEY = 'homebrewery-new'; const STYLEKEY = 'homebrewery-new-style'; const METAKEY = 'homebrewery-new-meta'; @@ -45,7 +47,8 @@ const PrintPage = createClass({ brew : { text : brewStorage, style : styleStorage, - renderer : metaStorage?.renderer || 'legacy' + renderer : metaStorage?.renderer || 'legacy', + theme : metaStorage?.theme || '5ePHB' } }; }); @@ -82,9 +85,16 @@ const PrintPage = createClass({ }, render : function(){ + const rendererPath = this.state.brew.renderer == 'V3' ? 'V3' : 'Legacy'; + const themePath = this.state.brew.theme ?? '5ePHB'; + const baseThemePath = Themes[rendererPath][themePath].baseTheme; + return
- + {baseThemePath && + + } + {/* Apply CSS from Style tab */} {this.renderStyle()}
diff --git a/client/homebrew/pages/sharePage/sharePage.jsx b/client/homebrew/pages/sharePage/sharePage.jsx index c983512ad..eb092b11e 100644 --- a/client/homebrew/pages/sharePage/sharePage.jsx +++ b/client/homebrew/pages/sharePage/sharePage.jsx @@ -86,7 +86,7 @@ const SharePage = createClass({
- +
; } diff --git a/scripts/buildHomebrew.js b/scripts/buildHomebrew.js index afdeb7e1f..ea5d1d0e2 100644 --- a/scripts/buildHomebrew.js +++ b/scripts/buildHomebrew.js @@ -10,7 +10,7 @@ const assetTransform = require('vitreum/transforms/asset.js'); const babel = require('@babel/core'); const less = require('less'); -const babelify = async (code)=>(await babel.transformAsync(code, { presets: ['@babel/preset-env', '@babel/preset-react'], plugins: ['@babel/plugin-transform-runtime'] })).code; +const babelify = async (code)=>(await babel.transformAsync(code, { presets: [['@babel/preset-env', { 'exclude': ['proposal-dynamic-import'] }], '@babel/preset-react'], plugins: ['@babel/plugin-transform-runtime'] })).code; const transforms = { '.js' : (code, filename, opts)=>babelify(code), @@ -24,29 +24,8 @@ const build = async ({ bundle, render, ssr })=>{ await fs.outputFile('./build/homebrew/bundle.css', css); await fs.outputFile('./build/homebrew/bundle.js', bundle); await fs.outputFile('./build/homebrew/ssr.js', ssr); - await fs.copy('./themes/fonts', './build/fonts'); - await fs.copy('./themes/assets', './build/assets'); + await fs.copy('./client/homebrew/favicon.ico', './build/assets/favicon.ico'); - let src = './themes/5ePhbLegacy.style.less'; - //Parse brew theme files - less.render(fs.readFileSync(src).toString(), { - compress : !isDev - }, function(e, output) { - fs.outputFile('./build/themes/5ePhbLegacy.style.css', output.css); - }); - src = './themes/5ePhb.style.less'; - less.render(fs.readFileSync(src).toString(), { - compress : !isDev - }, function(e, output) { - fs.outputFile('./build/themes/5ePhb.style.css', output.css); - }); - // await less.render(lessCode, { - // compress : !dev, - // sourceMap : (dev ? { - // sourceMapFileInline: true, - // outputSourceFiles: true - // } : false), - // }) //compress files in production if(!isDev){ @@ -61,16 +40,98 @@ const build = async ({ bundle, render, ssr })=>{ }; fs.emptyDirSync('./build'); -pack('./client/homebrew/homebrew.jsx', { - paths : ['./shared'], - libs : Proj.libs, - dev : isDev && build, - transforms -}) - .then(build) - .catch(console.error); +(async ()=>{ + + //v==----------------------------- COMPILE THEMES --------------------------------==v// + + // Update list of all Theme files + const themes = { Legacy: {}, V3: {} }; + + let themeFiles = fs.readdirSync('./themes/Legacy'); + for (dir of themeFiles) { + const themeData = JSON.parse(fs.readFileSync(`./themes/Legacy/${dir}/settings.json`).toString()); + themeData.path = dir; + themes.Legacy[dir] = (themeData); + //fs.copy(`./themes/Legacy/${dir}/dropdownTexture.png`, `./build/themes/Legacy/${dir}/dropdownTexture.png`); + const src = `./themes/Legacy/${dir}/style.less`; + ((outputDirectory)=>{ + less.render(fs.readFileSync(src).toString(), { + compress : !isDev + }, function(e, output) { + fs.outputFile(outputDirectory, output.css); + }); + })(`./build/themes/Legacy/${dir}/style.css`); + + } + + themeFiles = fs.readdirSync('./themes/V3'); + for (dir of themeFiles) { + const themeData = JSON.parse(fs.readFileSync(`./themes/V3/${dir}/settings.json`).toString()); + themeData.path = dir; + themes.V3[dir] = (themeData); + fs.copy(`./themes/V3/${dir}/dropdownTexture.png`, `./build/themes/V3/${dir}/dropdownTexture.png`); + const src = `./themes/V3/${dir}/style.less`; + ((outputDirectory)=>{ + less.render(fs.readFileSync(src).toString(), { + compress : !isDev + }, function(e, output) { + fs.outputFile(outputDirectory, output.css); + }); + })(`./build/themes/V3/${dir}/style.css`); + } + + await fs.outputFile('./themes/themes.json', JSON.stringify(themes, null, 2)); + + // await less.render(lessCode, { + // compress : !dev, + // sourceMap : (dev ? { + // sourceMapFileInline: true, + // outputSourceFiles: true + // } : false), + // }) + + // Move assets + await fs.copy('./themes/fonts', './build/fonts'); + await fs.copy('./themes/assets', './build/assets'); + + //v==----------------------------- BUNDLE PACKAGES --------------------------------==v// + + const bundles = await pack('./client/homebrew/homebrew.jsx', { + paths : ['./shared', './'], + libs : Proj.libs, + dev : isDev && build, + transforms + }); + build(bundles); + + // Possible method for generating separate bundles for theme snippets: factor-bundle first sending all common files to bundle.js, then again using default settings, keeping only snippet bundles + // await fs.outputFile('./build/junk.js', ''); + // await fs.outputFile('./build/themes/Legacy/5ePHB/snippets.js', ''); + // + // const files = ['./client/homebrew/homebrew.jsx','./themes/Legacy/5ePHB/snippets.js']; + // + // bundles = await pack(files, { + // dedupe: false, + // plugin : [['factor-bundle', { outputs: [ './build/junk.js','./build/themes/Legacy/5ePHB/snippets.js'], threshold : function(row, groups) { + // console.log(groups); + // if (groups.some(group => /.*homebrew.jsx$/.test(group))) { + // console.log("found homebrewery") + // return true; + // } + // return this._defaultThreshold(row, groups); + // }}]], + // paths : ['./shared','./','./build'], + // libs : Proj.libs, + // dev : isDev && build, + // transforms + // }); + // build(bundles); + // + +})().catch(console.error); + //In development set up a watch server and livereload if(isDev){ livereload('./build'); diff --git a/server/app.js b/server/app.js index cbbc3e3fe..98e2c778c 100644 --- a/server/app.js +++ b/server/app.js @@ -21,7 +21,7 @@ const splitTextStyleAndMetadata = (brew)=>{ const index = brew.text.indexOf('```\n\n'); const metadataSection = brew.text.slice(12, index - 1); const metadata = yaml.load(metadataSection); - Object.assign(brew, _.pick(metadata, ['title', 'description', 'tags', 'systems', 'renderer'])); + Object.assign(brew, _.pick(metadata, ['title', 'description', 'tags', 'systems', 'renderer', 'theme'])); brew.text = brew.text.slice(index + 5); } if(brew.text.startsWith('```css')) { @@ -29,6 +29,7 @@ const splitTextStyleAndMetadata = (brew)=>{ brew.style = brew.text.slice(7, index - 1); brew.text = brew.text.slice(index + 5); } + _.defaults(brew, { 'renderer': 'legacy', 'theme': '5ePHB' }); }; const sanitizeBrew = (brew, accessType)=>{ @@ -286,14 +287,15 @@ app.use(asyncHandler(async (req, res, next)=>{ environment : nodeEnv }; const props = { - version : require('./../package.json').version, - url : req.originalUrl, - brew : req.brew, - brews : req.brews, - googleBrews : req.googleBrews, - account : req.account, - enable_v3 : config.get('enable_v3'), - config : configuration + version : require('./../package.json').version, + url : req.originalUrl, + brew : req.brew, + brews : req.brews, + googleBrews : req.googleBrews, + account : req.account, + enable_v3 : config.get('enable_v3'), + enable_themes : config.get('enable_themes'), + config : configuration }; const title = req.brew ? req.brew.title : ''; const page = await templateFn('homebrew', title, props) diff --git a/server/homebrew.api.js b/server/homebrew.api.js index 52d8c6c37..8210fbb65 100644 --- a/server/homebrew.api.js +++ b/server/homebrew.api.js @@ -80,7 +80,7 @@ const mergeBrewText = (brew)=>{ `\`\`\`\n\n` + `${text}`; } - const metadata = _.pick(brew, ['title', 'description', 'tags', 'systems', 'renderer']); + const metadata = _.pick(brew, ['title', 'description', 'tags', 'systems', 'renderer', 'theme']); text = `\`\`\`metadata\n` + `${yaml.dump(metadata)}\n` + `\`\`\`\n\n` + diff --git a/shared/naturalcrit/nav/nav.jsx b/shared/naturalcrit/nav/nav.jsx index fde42a939..ef7d387e9 100644 --- a/shared/naturalcrit/nav/nav.jsx +++ b/shared/naturalcrit/nav/nav.jsx @@ -73,18 +73,35 @@ const Nav = { dropdown : createClass({ displayName : 'Nav.dropdown', + getDefaultProps : function() { + return { + trigger : 'hover' + }; + }, getInitialState : function() { return { showDropdown : false }; }, - + componentDidMount : function() { + if(this.props.trigger == 'click') + document.addEventListener('click', this.handleClickOutside); + }, + componentWillUnmount : function() { + if(this.props.trigger == 'click') + document.removeEventListener('click', this.handleClickOutside); + }, + handleClickOutside : function(e){ + // Close dropdown when clicked outside + if(this.refs.dropdown && !this.refs.dropdown.contains(e.target)) { + this.handleDropdown(false); + } + }, handleDropdown : function(show){ this.setState({ showDropdown : show }); }, - renderDropdown : function(dropdownChildren){ if(!this.state.showDropdown) return null; @@ -94,7 +111,6 @@ const Nav = {
); }, - render : function () { const dropdownChildren = React.Children.map(this.props.children, (child, i)=>{ // Ignore the first child @@ -102,10 +118,12 @@ const Nav = { return child; }); return ( -
this.handleDropdown(true)} - onMouseLeave={()=>this.handleDropdown(false)}> - {this.props.children[0]} +
{this.handleDropdown(true);} : undefined} + onClick= {this.props.trigger == 'click' ? ()=>{this.handleDropdown(true);} : undefined} + onMouseLeave={this.props.trigger == 'hover' ? ()=>{this.handleDropdown(false);} : undefined}> + {this.props.children[0] || this.props.children /*children is not an array when only one child*/} {this.renderDropdown(dropdownChildren)}
); diff --git a/shared/naturalcrit/styles/reset.less b/shared/naturalcrit/styles/reset.less index bdcdb83c3..be5bffc7e 100644 --- a/shared/naturalcrit/styles/reset.less +++ b/shared/naturalcrit/styles/reset.less @@ -1 +1,27 @@ -html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{border:0;font-size:100%;font:inherit;vertical-align:baseline;margin:0;padding:0}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:none}table{border-collapse:collapse;border-spacing:0} \ No newline at end of file +:where(html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video){ + border:0;font-size:100%;font:inherit;vertical-align:baseline;margin:0;padding:0 +} + +:where(article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section){ + display:block +} + +:where(body){ + line-height:1 +} + +:where(ol,ul){ + list-style:none +} + +:where(blockquote,q){ + quotes:none +} + +:where(blockquote:before,blockquote:after,q:before,q:after){ + content:none +} + +:where(table){ + border-collapse:collapse;border-spacing:0 +} diff --git a/themes/Legacy/5ePHB/settings.json b/themes/Legacy/5ePHB/settings.json new file mode 100644 index 000000000..98514e2a8 --- /dev/null +++ b/themes/Legacy/5ePHB/settings.json @@ -0,0 +1,5 @@ +{ + "name" : "5e PHB", + "renderer" : "legacy", + "baseTheme" : false +} diff --git a/client/homebrew/editor/snippetbar/snippetsLegacy/snippets.js b/themes/Legacy/5ePHB/snippets.js similarity index 93% rename from client/homebrew/editor/snippetbar/snippetsLegacy/snippets.js rename to themes/Legacy/5ePHB/snippets.js index 40c8405ac..e9134853c 100644 --- a/client/homebrew/editor/snippetbar/snippetsLegacy/snippets.js +++ b/themes/Legacy/5ePHB/snippets.js @@ -1,12 +1,12 @@ /* eslint-disable max-lines */ -const MagicGen = require('./magic.gen.js'); -const ClassTableGen = require('./classtable.gen.js'); -const MonsterBlockGen = require('./monsterblock.gen.js'); -const ClassFeatureGen = require('./classfeature.gen.js'); -const CoverPageGen = require('./coverpage.gen.js'); -const TableOfContentsGen = require('./tableOfContents.gen.js'); -const dedent = require('dedent-tabs').default; +const MagicGen = require('./snippets/magic.gen.js'); +const ClassTableGen = require('./snippets/classtable.gen.js'); +const MonsterBlockGen = require('./snippets/monsterblock.gen.js'); +const ClassFeatureGen = require('./snippets/classfeature.gen.js'); +const CoverPageGen = require('./snippets/coverpage.gen.js'); +const TableOfContentsGen = require('./snippets/tableOfContents.gen.js'); +const dedent = require('dedent-tabs').default; module.exports = [ diff --git a/client/homebrew/editor/snippetbar/snippetsLegacy/classfeature.gen.js b/themes/Legacy/5ePHB/snippets/classfeature.gen.js similarity index 100% rename from client/homebrew/editor/snippetbar/snippetsLegacy/classfeature.gen.js rename to themes/Legacy/5ePHB/snippets/classfeature.gen.js diff --git a/client/homebrew/editor/snippetbar/snippetsLegacy/classtable.gen.js b/themes/Legacy/5ePHB/snippets/classtable.gen.js similarity index 100% rename from client/homebrew/editor/snippetbar/snippetsLegacy/classtable.gen.js rename to themes/Legacy/5ePHB/snippets/classtable.gen.js diff --git a/client/homebrew/editor/snippetbar/snippetsLegacy/coverpage.gen.js b/themes/Legacy/5ePHB/snippets/coverpage.gen.js similarity index 100% rename from client/homebrew/editor/snippetbar/snippetsLegacy/coverpage.gen.js rename to themes/Legacy/5ePHB/snippets/coverpage.gen.js diff --git a/client/homebrew/editor/snippetbar/snippets/fullclass.gen.js b/themes/Legacy/5ePHB/snippets/fullclass.gen.js similarity index 100% rename from client/homebrew/editor/snippetbar/snippets/fullclass.gen.js rename to themes/Legacy/5ePHB/snippets/fullclass.gen.js diff --git a/client/homebrew/editor/snippetbar/snippetsLegacy/magic.gen.js b/themes/Legacy/5ePHB/snippets/magic.gen.js similarity index 100% rename from client/homebrew/editor/snippetbar/snippetsLegacy/magic.gen.js rename to themes/Legacy/5ePHB/snippets/magic.gen.js diff --git a/client/homebrew/editor/snippetbar/snippetsLegacy/monsterblock.gen.js b/themes/Legacy/5ePHB/snippets/monsterblock.gen.js similarity index 100% rename from client/homebrew/editor/snippetbar/snippetsLegacy/monsterblock.gen.js rename to themes/Legacy/5ePHB/snippets/monsterblock.gen.js diff --git a/client/homebrew/editor/snippetbar/snippetsLegacy/tableOfContents.gen.js b/themes/Legacy/5ePHB/snippets/tableOfContents.gen.js similarity index 100% rename from client/homebrew/editor/snippetbar/snippetsLegacy/tableOfContents.gen.js rename to themes/Legacy/5ePHB/snippets/tableOfContents.gen.js diff --git a/themes/5ePhbLegacy.style.less b/themes/Legacy/5ePHB/style.less similarity index 100% rename from themes/5ePhbLegacy.style.less rename to themes/Legacy/5ePHB/style.less diff --git a/themes/V3/5eDMG/dropdownTexture.png b/themes/V3/5eDMG/dropdownTexture.png new file mode 100644 index 000000000..bb74af94c Binary files /dev/null and b/themes/V3/5eDMG/dropdownTexture.png differ diff --git a/themes/V3/5eDMG/settings.json b/themes/V3/5eDMG/settings.json new file mode 100644 index 000000000..631ec1bf5 --- /dev/null +++ b/themes/V3/5eDMG/settings.json @@ -0,0 +1,6 @@ +{ + "name" : "5e DMG", + "renderer" : "V3", + "baseTheme" : "5ePHB", + "baseSnippets" : "5ePHB" +} diff --git a/themes/V3/5eDMG/snippets.js b/themes/V3/5eDMG/snippets.js new file mode 100644 index 000000000..636befb60 --- /dev/null +++ b/themes/V3/5eDMG/snippets.js @@ -0,0 +1,4 @@ +/* eslint-disable max-lines */ + +module.exports = [ +]; diff --git a/themes/V3/5eDMG/style.less b/themes/V3/5eDMG/style.less new file mode 100644 index 000000000..50a3af0a3 --- /dev/null +++ b/themes/V3/5eDMG/style.less @@ -0,0 +1,19 @@ +:root { + //Colors + --HB_Color_Accent : #EBCEC3; // Salmon + --HB_Color_Footnotes : #5C5C5C; // Dark gray +} + +.page { + background-image : url(/assets/DMG_background.png); + background-size : cover; + + &:after { + background-image : url(/assets/DMG_footerAccent.png); + height: 58px; + } + + .footnote { + bottom : 40px; + } +} diff --git a/themes/V3/5ePHB/dropdownTexture.png b/themes/V3/5ePHB/dropdownTexture.png new file mode 100644 index 000000000..d5884de16 Binary files /dev/null and b/themes/V3/5ePHB/dropdownTexture.png differ diff --git a/themes/V3/5ePHB/settings.json b/themes/V3/5ePHB/settings.json new file mode 100644 index 000000000..499096a05 --- /dev/null +++ b/themes/V3/5ePHB/settings.json @@ -0,0 +1,6 @@ +{ + "name" : "5e PHB", + "renderer" : "V3", + "baseTheme" : false, + "baseSnippets" : false +} diff --git a/themes/V3/5ePHB/snippets.js b/themes/V3/5ePHB/snippets.js new file mode 100644 index 000000000..bea2a1da3 --- /dev/null +++ b/themes/V3/5ePHB/snippets.js @@ -0,0 +1,264 @@ +/* eslint-disable max-lines */ + +const MagicGen = require('./snippets/magic.gen.js'); +const ClassTableGen = require('./snippets/classtable.gen.js'); +const MonsterBlockGen = require('./snippets/monsterblock.gen.js'); +const ClassFeatureGen = require('./snippets/classfeature.gen.js'); +const CoverPageGen = require('./snippets/coverpage.gen.js'); +const TableOfContentsGen = require('./snippets/tableOfContents.gen.js'); +const dedent = require('dedent-tabs').default; + + + +module.exports = [ + + { + groupName : 'Text Editor', + icon : 'fas fa-pencil-alt', + view : 'text', + snippets : [ + { + name : 'Page Number', + icon : 'fas fa-bookmark', + gen : '{{pageNumber 1}}\n{{footnote PART 1 | SECTION NAME}}\n\n' + }, + { + name : 'Auto-incrementing Page Number', + icon : 'fas fa-sort-numeric-down', + gen : '{{pageNumber,auto}}\n{{footnote PART 1 | SECTION NAME}}\n\n' + }, + { + name : 'Table of Contents', + icon : 'fas fa-book', + gen : TableOfContentsGen + } + ] + }, + { + groupName : 'Style Editor', + icon : 'fas fa-pencil-alt', + view : 'style', + snippets : [ + { + name : 'Remove Drop Cap', + icon : 'fas fa-remove-format', + gen : dedent`/* Removes Drop Caps */ + .page h1+p:first-letter { + all: unset; + }\n\n + /* Removes Small-Caps in first line */ + .page h1+p:first-line { + all: unset; + }` + }, + { + name : 'Tweak Drop Cap', + icon : 'fas fa-sliders-h', + gen : dedent`/* Drop Cap settings */ + .page h1 + p::first-letter { + font-family: SolberaImitationRemake; + font-size: 3.5cm; + background-image: linear-gradient(-45deg, #322814, #998250, #322814); + line-height: 1em; + }\n\n` + } + ] + }, + + /*********************** IMAGES *******************/ + { + groupName : 'Images', + icon : 'fas fa-images', + view : 'text', + snippets : [ + { + 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,mix-blend-mode:multiply} + + {{artist,position:relative,top:-230px,left:10px,margin-bottom:-30px + ##### Cat Warrior + [Kyoung Hwan Kim](https://www.artstation.com/tahra) + }}` + }, + { + name : 'Background Image', + icon : 'fas fa-tree', + gen : dedent` + ![homebrew mug](http://i.imgur.com/hMna6G0.png) {position:absolute,top:50px,right:30px,width:280px} + + {{artist,top:80px,right:30px + ##### Homebrew Mug + [naturalcrit](https://homebrew.naturalcrit.com) + }}` + }, + { + name : 'Watermark', + icon : 'fas fa-id-card', + gen : dedent` + {{watermark Homebrewery}}\n` + }, + ] + }, + + + /************************* PHB ********************/ + + { + groupName : 'PHB', + icon : 'fas fa-book', + view : 'text', + snippets : [ + { + name : 'Spell', + icon : 'fas fa-magic', + gen : MagicGen.spell, + }, + { + name : 'Spell List', + icon : 'fas fa-scroll', + gen : MagicGen.spellList, + }, + { + name : 'Class Feature', + icon : 'fas fa-mask', + gen : ClassFeatureGen, + }, + { + name : 'Note', + icon : 'fas fa-sticky-note', + gen : function(){ + return dedent` + {{note + ##### Time to Drop Knowledge + Use notes to point out some interesting information. + + **Tables and lists** both work within a note. + }} + \n`; + }, + }, + { + name : 'Descriptive Text Box', + icon : 'fas fa-comment-alt', + gen : function(){ + return dedent` + {{descriptive + ##### Time to Drop Knowledge + Use descriptive boxes to highlight text that should be read aloud. + + **Tables and lists** both work within a descriptive box. + }} + \n`; + }, + }, + { + name : 'Monster Stat Block (unframed)', + icon : 'fas fa-paw', + gen : MonsterBlockGen.monster('monster', 2), + }, + { + name : 'Monster Stat Block', + icon : 'fas fa-spider', + gen : MonsterBlockGen.monster('monster,frame', 2), + }, + { + name : 'Wide Monster Stat Block', + icon : 'fas fa-dragon', + gen : MonsterBlockGen.monster('monster,frame,wide', 4), + }, + { + name : 'Cover Page', + icon : 'fas fa-file-word', + gen : CoverPageGen, + }, + { + name : 'Magic Item', + 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`; + }, + }, + ] + }, + + + + /********************* TABLES *********************/ + + { + groupName : 'Tables', + icon : 'fas fa-table', + view : 'text', + snippets : [ + { + name : 'Class Table', + icon : 'fas fa-table', + gen : ClassTableGen.full('classTable,frame,decoration,wide'), + }, + { + name : 'Class Table (unframed)', + icon : 'fas fa-border-none', + gen : ClassTableGen.full('classTable,wide'), + }, + { + name : '1/2 Class Table', + icon : 'fas fa-list-alt', + gen : ClassTableGen.half('classTable,decoration,frame'), + }, + { + name : '1/2 Class Table (unframed)', + icon : 'fas fa-border-none', + gen : ClassTableGen.half('classTable'), + }, + { + name : '1/3 Class Table', + icon : 'fas fa-border-all', + gen : ClassTableGen.third('classTable,frame'), + }, + { + name : '1/3 Class Table (unframed)', + icon : 'fas fa-border-none', + gen : ClassTableGen.third('classTable'), + } + ] + }, + + + + + /**************** PAGE *************/ + + { + groupName : 'Print', + icon : 'fas fa-print', + view : 'style', + snippets : [ + { + name : 'Ink Friendly', + icon : 'fas fa-tint', + gen : dedent` + /* Ink Friendly */ + *:is(.page,.monster,.note,.descriptive) { + background : white !important; + filter : drop-shadow(0px 0px 3px #888) !important; + } + + .page img { + visibility : hidden; + }\n\n` + }, + ] + } +]; diff --git a/client/homebrew/editor/snippetbar/snippets/classfeature.gen.js b/themes/V3/5ePHB/snippets/classfeature.gen.js similarity index 99% rename from client/homebrew/editor/snippetbar/snippets/classfeature.gen.js rename to themes/V3/5ePHB/snippets/classfeature.gen.js index 1bd940c1f..2597c3ee8 100644 --- a/client/homebrew/editor/snippetbar/snippets/classfeature.gen.js +++ b/themes/V3/5ePHB/snippets/classfeature.gen.js @@ -17,15 +17,15 @@ module.exports = function(classname){ return dedent` ## Class Features - As a ${classname}, you gain the following class features - #### Hit Points + As a ${classname}, you gain the following class features + + #### Hit Points **Hit Dice:** :: 1d${hitDie} per ${classname} level **Hit Points at 1st Level:** :: ${hitDie} + your Constitution modifier **Hit Points at Higher Levels:** :: 1d${hitDie} (or ${hitDie/2 + 1}) + your Constitution modifier per ${classname} level after 1st #### Proficiencies - **Armor:** :: ${_.sampleSize(['Light armor', 'Medium armor', 'Heavy armor', 'Shields'], _.random(0, 3)).join(', ') || 'None'} **Weapons:** :: ${_.sampleSize(['Squeegee', 'Rubber Chicken', 'Simple weapons', 'Martial weapons'], _.random(0, 2)).join(', ') || 'None'} **Tools:** :: ${_.sampleSize(['Artisan\'s tools', 'one musical instrument', 'Thieves\' tools'], _.random(0, 2)).join(', ') || 'None'} @@ -34,7 +34,6 @@ module.exports = function(classname){ **Skills:** :: Choose two from ${_.sampleSize(skillList, _.random(4, 6)).join(', ')} #### Spellcasting Ability - {{text-align:center **Spell save DC**:: = ${_.sample([6, 8, 10])} + your proficiency bonus + your ${spellSkill} modifier @@ -46,6 +45,5 @@ module.exports = function(classname){ - *(a)* a martial weapon and a shield or *(b)* two martial weapons - *(a)* five javelins or *(b)* any simple melee weapon - ${_.sample(['10 lint fluffs', '1 button', 'a cherished lost sock'])} - `; }; diff --git a/client/homebrew/editor/snippetbar/snippets/classtable.gen.js b/themes/V3/5ePHB/snippets/classtable.gen.js similarity index 100% rename from client/homebrew/editor/snippetbar/snippets/classtable.gen.js rename to themes/V3/5ePHB/snippets/classtable.gen.js diff --git a/client/homebrew/editor/snippetbar/snippets/coverpage.gen.js b/themes/V3/5ePHB/snippets/coverpage.gen.js similarity index 100% rename from client/homebrew/editor/snippetbar/snippets/coverpage.gen.js rename to themes/V3/5ePHB/snippets/coverpage.gen.js diff --git a/client/homebrew/editor/snippetbar/snippetsLegacy/fullclass.gen.js b/themes/V3/5ePHB/snippets/fullclass.gen.js similarity index 100% rename from client/homebrew/editor/snippetbar/snippetsLegacy/fullclass.gen.js rename to themes/V3/5ePHB/snippets/fullclass.gen.js diff --git a/client/homebrew/editor/snippetbar/snippets/magic.gen.js b/themes/V3/5ePHB/snippets/magic.gen.js similarity index 100% rename from client/homebrew/editor/snippetbar/snippets/magic.gen.js rename to themes/V3/5ePHB/snippets/magic.gen.js diff --git a/client/homebrew/editor/snippetbar/snippets/monsterblock.gen.js b/themes/V3/5ePHB/snippets/monsterblock.gen.js similarity index 100% rename from client/homebrew/editor/snippetbar/snippets/monsterblock.gen.js rename to themes/V3/5ePHB/snippets/monsterblock.gen.js diff --git a/client/homebrew/editor/snippetbar/snippets/tableOfContents.gen.js b/themes/V3/5ePHB/snippets/tableOfContents.gen.js similarity index 100% rename from client/homebrew/editor/snippetbar/snippets/tableOfContents.gen.js rename to themes/V3/5ePHB/snippets/tableOfContents.gen.js diff --git a/client/homebrew/editor/snippetbar/snippets/watercolor.gen.js b/themes/V3/5ePHB/snippets/watercolor.gen.js similarity index 100% rename from client/homebrew/editor/snippetbar/snippets/watercolor.gen.js rename to themes/V3/5ePHB/snippets/watercolor.gen.js diff --git a/themes/5ePhb.style.less b/themes/V3/5ePHB/style.less similarity index 93% rename from themes/5ePhb.style.less rename to themes/V3/5ePHB/style.less index 6915c5753..98b52788f 100644 --- a/themes/5ePhb.style.less +++ b/themes/V3/5ePHB/style.less @@ -1,15 +1,19 @@ @import (less) './themes/fonts/5e/fonts.less'; @import (less) './themes/assets/assets.less'; -//Colors -@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 -@watercolorStain : #BBAD82; // Light brown +:root { + //Colors + --HB_Color_Background : #EEE5CE; // Light parchment + --HB_Color_Accent : #E0E5C1; // Pastel green + --HB_Color_HeaderUnderline : #C0AD6A; // Gold + --HB_Color_HorizontalRule : #9C2B1B; // Maroon + --HB_Color_HeaderText : #58180D; // Dark Maroon + --HB_Color_MonsterStatBackground : #EEDBAB; // Light orange parchment + --HB_Color_CaptionText : #766649; // Brown + --HB_Color_WatercolorStain : #BBAD82; // Light brown + --HB_Color_Footnotes : #C9AD6A; // Gold +} + @page { margin: 0; } body { counter-reset : phb-page-numbers; @@ -65,7 +69,7 @@ body { overflow : hidden; height : 279.4mm; width : 215.9mm; - background-color : @background; + background-color : var(--HB_Color_Background); background-image : @backgroundImage; padding : 1.4cm 1.9cm 1.7cm; font-family : BookInsanityRemake; @@ -131,12 +135,13 @@ body { h1,h2,h3,h4{ font-family : MrEavesRemake; font-weight : 800; - color : @headerText; + color : var(--HB_Color_HeaderText); } h1{ margin-bottom : 0.18cm; //Margin-bottom only because this is WIDE column-span : all; font-size : 0.89cm; + line-height : 1em; -webkit-column-span : all; -moz-column-span : all; &+p::first-letter{ @@ -168,7 +173,7 @@ body { //margin-top : -0.1cm; //Font is misaligned. Shift up slightly //margin-bottom : 0.1cm; font-size : 0.575cm; - border-bottom : 2px solid @headerUnderline; + border-bottom : 2px solid var(--HB_Color_HeaderUnderline);; line-height : 0.995em; //Font is misaligned. Shift up slightly } h4{ @@ -211,7 +216,7 @@ body { padding : 0.14em 0.4em; } &:nth-child(odd){ - background-color : @noteGreen; + background-color : var(--HB_Color_Accent); } } } @@ -221,7 +226,7 @@ body { // *****************************/ .note{ .useSansSerif(); - background-color : @noteGreen; + background-color : var(--HB_Color_Accent); border-style : solid; border-width : 1px; border-image : @noteBorderImage 12 stretch; @@ -287,7 +292,7 @@ body { text-align : center; font-family : WalterTurncoat; font-size : 0.27cm; - color : @captionText; + color : var(--HB_Color_CaptionText); p, p + p { margin : unset; text-indent : unset; @@ -340,7 +345,7 @@ body { mask-size : contain; mask-repeat : no-repeat; background-size : cover; - background-color : @watercolorStain; /*default color*/ + background-color : var(--HB_Color_WatercolorStain); /*default color*/ --wc : @watercolor1; /*default image*/ z-index : -2; } @@ -366,7 +371,7 @@ body { &.frame { border-style : solid; border-width : 7px 6px; - background-color : @monsterStatBackground; + background-color : var(--HB_Color_MonsterStatBackground); background-image : @monsterBlockBackground; border-image : @monsterBorderImage 14 round; border-image-outset : 0px 2px; @@ -397,7 +402,7 @@ body { font-family : ScalySansRemake; font-weight : 800; font-variant : small-caps; - border-bottom : 2px solid @headerText; + border-bottom : 2px solid var(--HB_Color_HeaderText); // margin-top : 0.05cm; //Font is misaligned. Shift up slightly padding-bottom : 0.05cm; } @@ -414,7 +419,7 @@ body { //Attribute Lists - All text between HRs is red hr ~ :is(dl,p) { - color : @headerText; + color : var(--HB_Color_HeaderText); } hr:last-of-type { & ~ :is(dl,p) { @@ -429,7 +434,7 @@ body { hr + table:first-of-type{ margin : 0; column-span : none; - color : @headerText; + color : var(--HB_Color_HeaderText); background-color : transparent; border-style : none; border-image : none; @@ -484,7 +489,7 @@ body { bottom : 22px; width : 50px; font-size : 0.9em; - color : #c9ad6a; + color : var(--HB_Color_Footnotes); text-align : center; text-indent : 0; &.auto::after { @@ -498,7 +503,7 @@ body { z-index : 150; width : 200px; font-size : 0.8em; - color : #c9ad6a; + color : var(--HB_Color_Footnotes); text-align : right; } //************************************ diff --git a/themes/V3/Blank/dropdownTexture.png b/themes/V3/Blank/dropdownTexture.png new file mode 100644 index 000000000..d0c0256c0 Binary files /dev/null and b/themes/V3/Blank/dropdownTexture.png differ diff --git a/themes/V3/Blank/settings.json b/themes/V3/Blank/settings.json new file mode 100644 index 000000000..3786248fb --- /dev/null +++ b/themes/V3/Blank/settings.json @@ -0,0 +1,6 @@ +{ + "name" : "Blank", + "renderer" : "V3", + "baseTheme" : false, + "baseSnippets" : false +} diff --git a/client/homebrew/editor/snippetbar/snippets/snippets.js b/themes/V3/Blank/snippets.js similarity index 55% rename from client/homebrew/editor/snippetbar/snippets/snippets.js rename to themes/V3/Blank/snippets.js index 10920a564..cd508cccb 100644 --- a/client/homebrew/editor/snippetbar/snippets/snippets.js +++ b/themes/V3/Blank/snippets.js @@ -1,13 +1,8 @@ /* eslint-disable max-lines */ -const MagicGen = require('./magic.gen.js'); -const ClassTableGen = require('./classtable.gen.js'); -const MonsterBlockGen = require('./monsterblock.gen.js'); -const ClassFeatureGen = require('./classfeature.gen.js'); -const CoverPageGen = require('./coverpage.gen.js'); -const TableOfContentsGen = require('./tableOfContents.gen.js'); -const dedent = require('dedent-tabs').default; -const watercolorGen = require('./watercolor.gen.js'); +const WatercolorGen = require('./snippets/watercolor.gen.js'); +const dedent = require('dedent-tabs').default; + module.exports = [ @@ -59,26 +54,11 @@ module.exports = [ `&size=100x100) {width:100px;mix-blend-mode:multiply}`; } }, - { - name : 'Page Number', - icon : 'fas fa-bookmark', - gen : '{{pageNumber 1}}\n{{footnote PART 1 | SECTION NAME}}\n\n' - }, - { - name : 'Auto-incrementing Page Number', - icon : 'fas fa-sort-numeric-down', - gen : '{{pageNumber,auto}}\n{{footnote PART 1 | SECTION NAME}}\n\n' - }, { name : 'Link to page', icon : 'fas fa-link', gen : '[Click here](#p3) to go to page 3\n' }, - { - name : 'Table of Contents', - icon : 'fas fa-book', - gen : TableOfContentsGen - }, { name : 'Add Comment', icon : 'fas fa-code', @@ -91,29 +71,6 @@ module.exports = [ icon : 'fas fa-pencil-alt', view : 'style', snippets : [ - { - name : 'Remove Drop Cap', - icon : 'fas fa-remove-format', - gen : dedent`/* Removes Drop Caps */ - .page h1+p:first-letter { - all: unset; - }\n\n - /* Removes Small-Caps in first line */ - .page h1+p:first-line { - all: unset; - }` - }, - { - name : 'Tweak Drop Cap', - icon : 'fas fa-sliders-h', - gen : dedent`/* Drop Cap settings */ - .page h1 + p::first-letter { - font-family: SolberaImitationRemake; - font-size: 3.5cm; - background-image: linear-gradient(-45deg, #322814, #998250, #322814); - line-height: 1em; - }\n\n` - }, { name : 'Add Comment', icon : 'fas fa-code', @@ -132,28 +89,18 @@ 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,mix-blend-mode:multiply} - - {{artist,position:relative,top:-230px,left:10px,margin-bottom:-30px - ##### Cat Warrior - [Kyoung Hwan Kim](https://www.artstation.com/tahra) - }}` + ![cat warrior](https://s-media-cache-ak0.pinimg.com/736x/4a/81/79/4a8179462cfdf39054a418efd4cb743e.jpg) {width:325px,mix-blend-mode:multiply}` }, { name : 'Background Image', icon : 'fas fa-tree', gen : dedent` - ![homebrew mug](http://i.imgur.com/hMna6G0.png) {position:absolute,top:50px,right:30px,width:280px} - - {{artist,top:80px,right:30px - ##### Homebrew Mug - [naturalcrit](https://homebrew.naturalcrit.com) - }}` + ![homebrew mug](http://i.imgur.com/hMna6G0.png) {position:absolute,top:50px,right:30px,width:280px}` }, { name : 'Watercolor Splatter', icon : 'fas fa-fill-drip', - gen : watercolorGen, + gen : WatercolorGen, }, { name : 'Watermark', @@ -164,99 +111,6 @@ module.exports = [ ] }, - - /************************* PHB ********************/ - - { - groupName : 'PHB', - icon : 'fas fa-book', - view : 'text', - snippets : [ - { - name : 'Spell', - icon : 'fas fa-magic', - gen : MagicGen.spell, - }, - { - name : 'Spell List', - icon : 'fas fa-scroll', - gen : MagicGen.spellList, - }, - { - name : 'Class Feature', - icon : 'fas fa-mask', - gen : ClassFeatureGen, - }, - { - name : 'Note', - icon : 'fas fa-sticky-note', - gen : function(){ - return dedent` - {{note - ##### Time to Drop Knowledge - Use notes to point out some interesting information. - - **Tables and lists** both work within a note. - }} - \n`; - }, - }, - { - name : 'Descriptive Text Box', - icon : 'fas fa-comment-alt', - gen : function(){ - return dedent` - {{descriptive - ##### Time to Drop Knowledge - Use descriptive boxes to highlight text that should be read aloud. - - **Tables and lists** both work within a descriptive box. - }} - \n`; - }, - }, - { - name : 'Monster Stat Block (unframed)', - icon : 'fas fa-paw', - gen : MonsterBlockGen.monster('monster', 2), - }, - { - name : 'Monster Stat Block', - icon : 'fas fa-spider', - gen : MonsterBlockGen.monster('monster,frame', 2), - }, - { - name : 'Wide Monster Stat Block', - icon : 'fas fa-dragon', - gen : MonsterBlockGen.monster('monster,frame,wide', 4), - }, - { - name : 'Cover Page', - icon : 'fas fa-file-word', - gen : CoverPageGen, - }, - { - name : 'Magic Item', - 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`; - }, - }, - ] - }, - - - /********************* TABLES *********************/ { @@ -323,43 +177,10 @@ module.exports = [ }} \n`; } - }, - { - name : 'Class Table', - icon : 'fas fa-table', - gen : ClassTableGen.full('classTable,frame,decoration,wide'), - }, - { - name : 'Class Table (unframed)', - icon : 'fas fa-border-none', - gen : ClassTableGen.full('classTable,wide'), - }, - { - name : '1/2 Class Table', - icon : 'fas fa-list-alt', - gen : ClassTableGen.half('classTable,decoration,frame'), - }, - { - name : '1/2 Class Table (unframed)', - icon : 'fas fa-border-none', - gen : ClassTableGen.half('classTable'), - }, - { - name : '1/3 Class Table', - icon : 'fas fa-border-all', - gen : ClassTableGen.third('classTable,frame'), - }, - { - name : '1/3 Class Table (unframed)', - icon : 'fas fa-border-none', - gen : ClassTableGen.third('classTable'), } ] }, - - - /**************** PAGE *************/ { @@ -392,7 +213,7 @@ module.exports = [ icon : 'fas fa-tint', gen : dedent` /* Ink Friendly */ - *:is(.page,.monster,.note,.descriptive) { + *:is(.page) { background : white !important; filter : drop-shadow(0px 0px 3px #888) !important; } @@ -402,6 +223,5 @@ module.exports = [ }\n\n` }, ] - }, - + } ]; diff --git a/themes/V3/Blank/snippets/watercolor.gen.js b/themes/V3/Blank/snippets/watercolor.gen.js new file mode 100644 index 000000000..735a35602 --- /dev/null +++ b/themes/V3/Blank/snippets/watercolor.gen.js @@ -0,0 +1,5 @@ +const _ = require('lodash'); + +module.exports = ()=>{ + return `{{watercolor${_.random(1, 12)},top:20px,left:30px,width:300px,background-color:#BBAD82,opacity:80%}}\n\n`; +}; diff --git a/themes/V3/Blank/style.less b/themes/V3/Blank/style.less new file mode 100644 index 000000000..668be712e --- /dev/null +++ b/themes/V3/Blank/style.less @@ -0,0 +1,273 @@ +@import (less) './themes/fonts/5e/fonts.less'; +@import (less) './themes/assets/assets.less'; + +:root { + //Colors + --HB_Color_Background : #FFFFFF; // White + --HB_Color_WatercolorStain : #000000; // Black +} + +@page { margin: 0; } +body { + counter-reset : phb-page-numbers; +} +*{ + -webkit-print-color-adjust : exact; +} + +.useColumns(@multiplier : 1, @fillMode: balance){ + column-fill : @fillMode; + column-count : 2; +} +.columnWrapper{ + max-height : 100%; + column-span : all; + columns : inherit; + column-gap : inherit; +} +.page{ + .useColumns(); + height : 279.4mm; + width : 215.9mm; + padding : 1.4cm 1.9cm 1.7cm; + counter-increment : phb-page-numbers; + background-color : var(--HB_Color_Background); + position : relative; + z-index : 15; + box-sizing : border-box; + overflow : hidden; + text-rendering : optimizeLegibility; + page-break-before : always; + page-break-after : always; +} + //***************************** + // * BASE + // *****************************/ +:where(.page){ + p{ + overflow-wrap : break-word; + display : block; + } + strong{ + font-weight : bold; + } + em{ + font-style : italic; + } + sup{ + vertical-align : super; + font-size : smaller; + line-height : 0; + } + sub{ + vertical-align : sub; + font-size : smaller; + line-height : 0; + } + ul { + list-style-position : outside; //Needed for multiline list items + list-style-type : disc; + padding-left : 1.4em; + } + ol { + list-style-position : outside; + list-style-type : decimal; + padding-left : 1.4em; + } + img{ + z-index : -1; + } + :not(:where(.wide,.columnSplit,.blank,hr)) + :where(h1,h2,h3,h4,h5,h6,table,dl,.block) { + margin-top : 1em; //NOTE: MAKE ALL MARGINS TOP-ONLY FOR BEST RESULTS WITH COLUMN BREAKS. USE * + * STYLE SELECTORS + } + + :where(h1,h3,h3,h4,h5,h6) + * { + margin-top : 0; + } + //***************************** + // * HEADERS + // *****************************/ + h1,h2,h3,h4,h5,h6{ + font-weight : bold; + line-height : 1.2em; + } + h1{ + font-size : 2em; + } + h2{ + font-size : 1.5em; + } + h3{ + font-size : 1.17em; + } + h4{ + font-size : 1em; + } + h5{ + font-size : 0.83em; + } + //***************************** + // * TABLE + // *****************************/ + table{ + width : 100%; + thead{ + display : table-row-group; + font-weight : bold; + } + } + + /* Watermark */ + .watermark { + display : grid !important; + place-items : center; + justify-content : center; + position : absolute; + margin : 0; + top : 0; + left : 0; + width : 100%; + height : 100%; + font-size : 120px; + text-transform : uppercase; + color : black; + mix-blend-mode : overlay; + opacity : 30%; + transform : rotate(-45deg); + z-index : 500; + p { + margin-bottom : none; + } + } + + /* Watercolor */ + [class*="watercolor"] { + position : absolute; + width : 2000px; /* dimensions need to be real big so the user can set */ + height : 2000px; /* height or width and the image will maintain aspect ratio */ + -webkit-mask-image : var(--wc); + -webkit-mask-size : contain; + -webkit-mask-repeat : no-repeat; + mask-image : var(--wc); + mask-size : contain; + mask-repeat : no-repeat; + background-size : cover; + background-color : var(--HB_Color_WatercolorStain); /*default color*/ + --wc : @watercolor1; /*default image*/ + z-index : -2; + } + + .watercolor1 { --wc : @watercolor1; } + .watercolor2 { --wc : @watercolor2; } + .watercolor3 { --wc : @watercolor3; } + .watercolor4 { --wc : @watercolor4; } + .watercolor5 { --wc : @watercolor5; } + .watercolor6 { --wc : @watercolor6; } + .watercolor7 { --wc : @watercolor7; } + .watercolor8 { --wc : @watercolor8; } + .watercolor9 { --wc : @watercolor9; } + .watercolor10 { --wc : @watercolor10; } + .watercolor11 { --wc : @watercolor11; } + .watercolor12 { --wc : @watercolor12; } + + //************************************ + // * CODE BLOCKS + // ************************************/ + code{ + font-family : "Courier New", Courier, monospace; + white-space : pre-wrap; + overflow-wrap : break-word; + } + + pre code{ + width : 100%; + display : inline-block; + } + //***************************** + // * EXTRAS + // *****************************/ + .columnSplit { + visibility : hidden; + -webkit-column-break-after : always; + break-after : always; + -moz-column-break-after : always; + } + //Avoid breaking up + blockquote,table{ + z-index : 15; + -webkit-column-break-inside : avoid; + page-break-inside : avoid; + break-inside : avoid; + } + // Nested lists + ul ul,ol ol,ul ol,ol ul{ + margin-bottom : 0px; + margin-left : 1.5em; + } + li{ + -webkit-column-break-inside : avoid; + page-break-inside : avoid; + break-inside : avoid; + } +} + +//***************************** +// * MUSTACHE DIVS/SPANS +// *****************************/ +:where(.page) { + .block { + break-inside : avoid; + display : inline-block; + .page :where(&) { + width : 100%; + } + } + .inline-block { + display : inline-block; + text-indent : initial; + } +} + +//***************************** +// * DEFINITION LISTS +// *****************************/ +:where(.page) { + dl { + padding-left : 1em; + white-space : pre-line; + } + dt { + display : inline; + margin-right : 0.5ch; + margin-left : -1em; + } + dd { + display : inline; + margin-left : 0; + text-indent : 0; + } +} + +//***************************** +// * BLANK LINE +// *****************************/ +:where(.page) { + .blank { + height : 1em; + margin-top : 0; + } +} + +//***************************** +// * WIDE +// *****************************/ +:where(.page) { + .wide{ + column-span : all; + display : block; + margin-bottom : 1em; + &+* { + margin-top : 0; + } + } +} diff --git a/themes/V3/Journal/dropdownTexture.png b/themes/V3/Journal/dropdownTexture.png new file mode 100644 index 000000000..558b82d19 Binary files /dev/null and b/themes/V3/Journal/dropdownTexture.png differ diff --git a/themes/V3/Journal/settings.json b/themes/V3/Journal/settings.json new file mode 100644 index 000000000..069bdb270 --- /dev/null +++ b/themes/V3/Journal/settings.json @@ -0,0 +1,6 @@ +{ + "name" : "Journal", + "renderer" : "V3", + "baseTheme" : false, + "baseSnippets" : "5ePHB" +} diff --git a/themes/V3/Journal/snippets.js b/themes/V3/Journal/snippets.js new file mode 100644 index 000000000..636befb60 --- /dev/null +++ b/themes/V3/Journal/snippets.js @@ -0,0 +1,4 @@ +/* eslint-disable max-lines */ + +module.exports = [ +]; diff --git a/themes/V3/Journal/style.less b/themes/V3/Journal/style.less new file mode 100644 index 000000000..a06f60b6f --- /dev/null +++ b/themes/V3/Journal/style.less @@ -0,0 +1,559 @@ +@import (less) './themes/fonts/Journal/fonts.less'; +@import (less) './themes/assets/assets.less'; + +:root { + //Colors + --HB_Color_Background : unset; // Light parchment + --HB_Color_Text : #412121; // Dark Maroon Brown + --HB_Color_Text2 : #261C13CC; //Dark Brown + --HB_Color_HeaderText : #58180D; // Dark Maroon + --HB_Color_CaptionText : #766649; // Brown + --HB_Color_WatercolorStain : #BBAD82; // Light brown +} + +.useSansSerif(){ + font-family : PermanentMarker; + font-size : 0.3cm; + line-height : 1.2em; + color : var(--HB_Color_Text2); + p,dl,ul,ol { + line-height : 1.2em; + } + ul, ol { + padding-left : 1em; + } + em{ + font-style : italic; + } + strong{ + font-weight : 800; + font-size : 1.1em; + } + h5 + * { + margin-top : 0.1cm; + } +} +.useColumns(@multiplier : 1, @fillMode: balance){ + column-gap : 0.5cm; +} + +.page{ + background-size : 200% 100%; + background-repeat : no-repeat; + filter : drop-shadow(1px 4px 14px black); + background-image : url(/assets/Journal/Background1.webp); + padding : 2.1cm 1.9cm 1.7cm 3.8cm; + &:nth-of-type(2n + 1) { + background-position : left; + } + &:nth-of-type(2n) { + background-position : right; + padding : 2.1cm 3.9cm 1.7cm 1.8cm; + } + &:nth-of-type(2) { + background-image : url(/assets/Journal/Background2.webp); //Only first page should show ribbon + } + + & .columnWrapper { + //transform: rotate(-0.5deg); // Breaks absolute positioning of images/footers. Wait for Chrome fix + } +} + + //***************************** + // * BASE + // *****************************/ +:where(.page){ + color : var(--HB_Color_Text); + font-family : ReenieBeanie; + font-size : 0.53cm; + line-height : 0.8em; + p + * { + margin-top : 0.325cm; + } + p + p{ + margin-top : 0; + } + ul{ + margin-bottom : 0.8em; + } + ol{ + margin-bottom : 0.8em; + } + em{ + text-decoration : underline; + font-style : unset; + } + del{ + text-decoration-style: double; + } + + //Indents after p or lists + p+p, ul+p, ol+p{ + text-indent : 1em; + } + //***************************** + // * HEADERS + // *****************************/ + h1,h2,h3,h4,h5{ + font-family : FrederickaTheGreat; + font-weight : unset; + color : var(--HB_Color_HeaderText); + } + h1{ + margin-bottom : 0.18cm; //Margin-bottom only because this is WIDE + font-size : 0.89cm; + line-height : 1em; + font-variant : small-caps; + &+p::first-letter{ + float : left; + font-family : FrederickaTheGreat; + line-height : 1em; + font-size : 1.9em; + padding-left : 40px; //Allow background color to extend into margins + margin-top : -0.3cm; + margin-bottom : -20px; + margin-left : -40px; + margin-right : 0.1em; + padding-top : 0.3em; + padding-bottom : 2px; + } + &+p::first-line{ + font-variant : small-caps; + } + } + h2{ + font-size : 0.62cm; + line-height : 0.988em; //Font is misaligned. Shift up slightly + } + h3{ + font-size : 0.575cm; + line-height : 0.995em; //Font is misaligned. Shift up slightly + margin-left : -0.9em; + } + h4{ + font-size : 0.55cm; + line-height : 0.971em; //Font is misaligned. Shift up slightly + color : var(--HB_Color_Text); + padding-bottom : 5px; + transform:rotate(0deg); + &:nth-of-type(2n) { + transform:rotate(1deg); + } + &:nth-of-type(3n) { + transform:rotate(-1.5deg); + } + } + h5{ + font-family : PermanentMarker; + font-size : 0.4cm; + color : var(--HB_Color_Text2); + font-weight : bold; + line-height : 0.951em; //Font is misaligned. Shift up slightly + & + * { + margin-top : 0.2cm; + } + } + //***************************** + // * TABLE + // *****************************/ + table{ + .useSansSerif(); + & + * { + margin-top : 0.325cm; + } + thead{ + th{ + vertical-align : bottom; + padding : 0.14em 0; + } + } + tbody{ + tr{ + td{ + padding : 0.14em 0; + } + &:nth-child(odd){ + background-image : linear-gradient(to left, #41212100, #41212122, #41212100); + } + } + } + } + //***************************** + // * NOTE + // *****************************/ + .note{ + .useSansSerif(); + border-style : solid; + border-width : 1px; + border-image-source : url(/assets/Journal/Border1.png); + border-image-slice : 18 18 18 18; + border-image-width : 6px 6px 6px 6px; + border-image-outset : 5px 5px 5px 5px; + border-image-repeat : stretch stretch; + background-image : url(/assets/Journal/HashMarks.png), + linear-gradient(to bottom right, #ff000000, #a36a4e14, #41212100); + background-size : 120% 120%; + background-repeat : no-repeat; + background-position : center; + padding : 0.2cm; + :where(&) { + margin-top : 9px; //Prevent top border getting cut off on colbreak + } + & + * { + margin-top : 0.45cm; + } + h5 { + font-size : 0.375cm; + } + p{ + padding-bottom : 0px; + } + :last-child { + margin-bottom : 0; + } + } + //************************************ + // * DESCRIPTIVE TEXT BOX + // ************************************/ + * + .descriptive { + margin-top : 0.6cm; + } + .descriptive{ + .useSansSerif(); + border-style : solid; + border-width : 1px; + border-image-source : url('/assets/Journal/Border2.png'); + border-image-slice : 48 48 48 48; + border-image-width : 20px; + border-image-outset : 16px 20px 16px 20px; + border-image-repeat : stretch stretch; + background-image : url(/assets/Journal/HashMarks.png), + linear-gradient(to bottom right, #ff000000, #41212114, #41212100); + background-size : 120% 120%; + background-repeat : no-repeat; + background-position : center; + padding : 0.2cm; + :where(&) { + margin-top : 4px; //Prevent top border getting cut off on colbreak + } + & + * { + margin-top : 0.45cm; + } + h5 { + font-size : 0.375cm; + } + p{ + padding-bottom : 0px; + } + :last-child { + margin-bottom : 0; + } + } + //***************************** + // * Images Snippets + // *****************************/ + + /* Arist Credit */ + .artist { + position : absolute; + width : auto; + text-align : center; + font-family : WalterTurncoat; + font-size : 0.27cm; + color : var(--HB_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 + // *****************************/ + .monster { + .useSansSerif(); + &.frame { + border-style : solid; + border-width : 7px 6px; + border-image-source : url('/assets/Journal/Border3.png'); + border-image-slice : 63 74 63 74; + border-image-width : 15px 20px 15px 20px; + border-image-outset : 12px 12px 12px 12px; + border-image-repeat : stretch round; + background-image : url('/assets/Journal/HashMarks.png'), + linear-gradient(to bottom right, #ff000000, #a36a4e14, #41212100); + background-blend-mode : screen multiply; + background-size : 100%; + padding : 0.2cm; + } + + color: var(--HB_Color_Text); + position : relative; + padding : 0px; + margin-bottom : 0.325cm; + + //Headers + h2{ + font-size : 0.62cm; + line-height : 1em; + margin : 0; + &+p { + margin-bottom : 0; //Monster size and type subtext + } + } + h3{ + margin-left : 0; + font-variant : small-caps; + padding-bottom : 0.05cm; + } + hr{ + visibility : visible; + height : 6px; + margin : 0.12cm 0cm; + background-image : url('/assets/Journal/HorizontalRule.png'); + background-size : 100% 100%; + } + hr:last-of-type + * { + margin-top : 0.325cm; // Space after last HR + } + + // Monster Ability table + hr + table:first-of-type{ + margin : 0; + column-span : none; + background-image : none; + border-style : none; + border-image : none; + color : inherit; + tr { + background-image : none; + } + td,th { + padding: 0px; + } + } + + :last-child { + margin-bottom : 0; + } + + strong, em { + font-style : normal; + text-decoration : none; + } + } + + //Full Width + .monster.wide{ + .useColumns(0.96, @fillMode: balance); + } + + //***************************** + // * FOOTER + // *****************************/ + &:nth-child(odd){ + .pageNumber{ + left : 3cm; + } + .footnote{ + left : 4.5cm; + text-align : left; + } + } + .pageNumber{ + font-family : FrederickaTheGreat; + position : absolute; + right : 3cm; + bottom : 1.25cm; + width : 50px; + font-size : 0.9em; + color : var(--HB_Color_HeaderText); + text-align : center; + text-indent : 0; + &.auto::after { + content : counter(phb-page-numbers); + } + } + .footnote{ + position : absolute; + right : 4.5cm; + bottom : 1.25cm; + z-index : 150; + width : 200px; + font-size : 0.8em; + color : var(--HB_Color_HeaderText); + text-align : right; + } + //************************************ + // * CODE BLOCKS + // ************************************/ + code{ + font-size : 0.3cm; + padding : 0px 4px; + color : var(--HB_Color_Text); + vertical-align : middle; + background-color : #faf7ea; + border-radius : 4px; + } + + pre code{ + border-style : solid; + border-width : 1px; + border-image : @codeBorderImage 26 stretch; + border-image-width : 10px; + border-image-outset : 2px; + border-radius : 12px; + margin-bottom : 2px; + padding : 0.15cm; + .page :where(&) { + margin-top : 2px; //Prevent top border getting cut off on colbreak + } + & + * { + margin-top : 0.325cm; + } + } + //***************************** + // * EXTRAS + // *****************************/ + hr{ + visibility : hidden; + border : none; + margin : 0px; + } + //Text indent right after table + table+p{ + text-indent : 1em; + } + a, a:visited, a:hover { + color: var(--HB_Color_Text); + transition:all 1s ease; + } + a:hover { + color:red; + } +} +//***************************** +// * SPELL LIST +// *****************************/ + +.page .spellList{ + .useSansSerif(); + font-family : PermanentMarker; + column-count : 2; + ul+h5{ + margin-top : 15px; + } + ul{ + margin-bottom : 0.5em; + padding-left : 1em; + text-indent : -1em; + list-style-type : none; + -webkit-column-break-inside : auto; + page-break-inside : auto; + break-inside : auto; + } + &.wide{ + column-count : 4; + } +} + +//***************************** +// * CLASS TABLE +// *****************************/ +.page .classTable{ + th[colspan]:not([rowspan]) { + white-space : nowrap; + } + h5 + table{ + margin-top : 0.2cm; + } +} +//***************************** +// * TABLE OF CONTENTS +// *****************************/ +.page .toc{ + -webkit-column-break-inside : avoid; + page-break-inside : avoid; + break-inside : avoid; + h1 { + text-align : center; + margin-bottom : 0.3cm; + } + a{ + display : inline; + color : inherit; + text-decoration : none; + &:hover{ + text-decoration : underline; + } + } + h4 { + margin-top : 0.2cm; + line-height : 0.4cm; + & + ul li { + line-height: 1.2em; + } + } + ul{ + padding-left : 0; + list-style-type : none; + li + li h3 { + margin-top : 0.26cm; + line-height : 1em + } + h3 span:first-child::after { + border : none; + } + span { + display : table-cell; + &:first-child { + position : relative; + overflow : hidden; + &::after { + content : ""; + position : absolute; + bottom : 0.08cm; + margin-left : 0.06cm; /* Spacing before dot leaders */ + width : 100%; + border-bottom : 0.05cm dotted #000; + } + } + &:last-child { + font-family : ReenieBeanie; + font-size : 0.34cm; + font-weight : normal; + color : black; + text-align : right; + vertical-align : bottom; /* Keep page number bottom-aligned */ + width : 1%; + padding-left : 0.06cm; /* Spacing after dot leaders */ + /*white-space : nowrap; /* Uncomment if needed */ + } + } + ul { /*List indent*/ + margin-left : 1em; + } + } + &.wide{ + .useColumns(0.96, @fillMode: balance); + } +} + +//***************************** +// * WIDE +// *****************************/ +:where(.page) .wide { + margin-bottom : 0.45cm; +} diff --git a/themes/assets/DMG_background.png b/themes/assets/DMG_background.png new file mode 100644 index 000000000..5fbccf9a8 Binary files /dev/null and b/themes/assets/DMG_background.png differ diff --git a/themes/assets/DMG_footerAccent.png b/themes/assets/DMG_footerAccent.png new file mode 100644 index 000000000..cc115709a Binary files /dev/null and b/themes/assets/DMG_footerAccent.png differ diff --git a/themes/assets/Journal/Background1.webp b/themes/assets/Journal/Background1.webp new file mode 100644 index 000000000..01cfb9bc4 Binary files /dev/null and b/themes/assets/Journal/Background1.webp differ diff --git a/themes/assets/Journal/Background2.webp b/themes/assets/Journal/Background2.webp new file mode 100644 index 000000000..7c6198107 Binary files /dev/null and b/themes/assets/Journal/Background2.webp differ diff --git a/themes/assets/Journal/Border1.png b/themes/assets/Journal/Border1.png new file mode 100644 index 000000000..f7e4cb763 Binary files /dev/null and b/themes/assets/Journal/Border1.png differ diff --git a/themes/assets/Journal/Border2.png b/themes/assets/Journal/Border2.png new file mode 100644 index 000000000..8f38c3f25 Binary files /dev/null and b/themes/assets/Journal/Border2.png differ diff --git a/themes/assets/Journal/Border3.png b/themes/assets/Journal/Border3.png new file mode 100644 index 000000000..ee033a712 Binary files /dev/null and b/themes/assets/Journal/Border3.png differ diff --git a/themes/assets/Journal/HashMarks.png b/themes/assets/Journal/HashMarks.png new file mode 100644 index 000000000..d587019f2 Binary files /dev/null and b/themes/assets/Journal/HashMarks.png differ diff --git a/themes/assets/Journal/HashMarksLight.png b/themes/assets/Journal/HashMarksLight.png new file mode 100644 index 000000000..7b4bcd2b7 Binary files /dev/null and b/themes/assets/Journal/HashMarksLight.png differ diff --git a/themes/assets/Journal/HashMarksLight2.png b/themes/assets/Journal/HashMarksLight2.png new file mode 100644 index 000000000..b8896db03 Binary files /dev/null and b/themes/assets/Journal/HashMarksLight2.png differ diff --git a/themes/assets/Journal/HorizontalRule.png b/themes/assets/Journal/HorizontalRule.png new file mode 100644 index 000000000..696a42a2b Binary files /dev/null and b/themes/assets/Journal/HorizontalRule.png differ diff --git a/themes/assets/footerAccent.png b/themes/assets/PHB_footerAccent.png similarity index 100% rename from themes/assets/footerAccent.png rename to themes/assets/PHB_footerAccent.png diff --git a/themes/assets/assets.less b/themes/assets/assets.less index 8790b1e59..7df5db0f6 100644 --- a/themes/assets/assets.less +++ b/themes/assets/assets.less @@ -1,26 +1,26 @@ // PHB -@footerAccentImage : data-uri('./themes/assets/footerAccent.png'); -@frameBorderImage : data-uri('./themes/assets/frameBorder.png'); -@backgroundImage : data-uri('./themes/assets/parchmentBackground.jpg'); -@redTriangleImage : data-uri('./themes/assets/redTriangle.png'); -@monsterBorderImageLegacy : data-uri('./themes/assets/monsterBorderLegacy.png'); -@noteBorderImage : data-uri('./themes/assets/noteBorder.png'); -@descriptiveBoxImage : data-uri('./themes/assets/descriptiveBorder.png'); -@monsterBlockBackground : data-uri('./themes/assets/parchmentBackgroundGrayscale.jpg'); -@monsterBorderImage : data-uri('./themes/assets/monsterBorderFancy.png'); -@codeBorderImage : data-uri('./themes/assets/codeBorder.png'); -@classTableDecoration : data-uri('./themes/assets/classTableDecoration.png'); +@footerAccentImage : url('/assets/PHB_footerAccent.png'); +@frameBorderImage : url('/assets/frameBorder.png'); +@backgroundImage : url('/assets/parchmentBackground.jpg'); +@redTriangleImage : url('/assets/redTriangle.png'); +@monsterBorderImageLegacy : url('/assets/monsterBorderLegacy.png'); +@noteBorderImage : url('/assets/noteBorder.png'); +@descriptiveBoxImage : url('/assets/descriptiveBorder.png'); +@monsterBlockBackground : url('/assets/parchmentBackgroundGrayscale.jpg'); +@monsterBorderImage : url('/assets/monsterBorderFancy.png'); +@codeBorderImage : url('/assets/codeBorder.png'); +@classTableDecoration : url('/assets/classTableDecoration.png'); // Watercolor Images -@watercolor1 : data-uri('./themes/assets/watercolor/watercolor1.png'); -@watercolor2 : data-uri('./themes/assets/watercolor/watercolor2.png'); -@watercolor3 : data-uri('./themes/assets/watercolor/watercolor3.png'); -@watercolor4 : data-uri('./themes/assets/watercolor/watercolor4.png'); -@watercolor5 : data-uri('./themes/assets/watercolor/watercolor5.png'); -@watercolor6 : data-uri('./themes/assets/watercolor/watercolor6.png'); -@watercolor7 : data-uri('./themes/assets/watercolor/watercolor7.png'); -@watercolor8 : data-uri('./themes/assets/watercolor/watercolor8.png'); -@watercolor9 : data-uri('./themes/assets/watercolor/watercolor9.png'); -@watercolor10 : data-uri('./themes/assets/watercolor/watercolor10.png'); -@watercolor11 : data-uri('./themes/assets/watercolor/watercolor11.png'); -@watercolor12 : data-uri('./themes/assets/watercolor/watercolor12.png'); +@watercolor1 : url('/assets/watercolor/watercolor1.png'); +@watercolor2 : url('/assets/watercolor/watercolor2.png'); +@watercolor3 : url('/assets/watercolor/watercolor3.png'); +@watercolor4 : url('/assets/watercolor/watercolor4.png'); +@watercolor5 : url('/assets/watercolor/watercolor5.png'); +@watercolor6 : url('/assets/watercolor/watercolor6.png'); +@watercolor7 : url('/assets/watercolor/watercolor7.png'); +@watercolor8 : url('/assets/watercolor/watercolor8.png'); +@watercolor9 : url('/assets/watercolor/watercolor9.png'); +@watercolor10 : url('/assets/watercolor/watercolor10.png'); +@watercolor11 : url('/assets/watercolor/watercolor11.png'); +@watercolor12 : url('/assets/watercolor/watercolor12.png'); diff --git a/themes/fonts/5e legacy/fonts.less b/themes/fonts/5e legacy/fonts.less index a3527130b..d4c10c456 100644 --- a/themes/fonts/5e legacy/fonts.less +++ b/themes/fonts/5e legacy/fonts.less @@ -1,25 +1,25 @@ /* Main Font, serif */ @font-face { font-family: BookSanity; - src: url('../fonts/5e legacy/Bookinsanity.woff2'); + src: url('../../../fonts/5e legacy/Bookinsanity.woff2'); font-weight: normal; font-style: normal; } @font-face { font-family: BookSanity; - src: url('../fonts/5e legacy/Bookinsanity Bold.woff2'); + src: url('../../../fonts/5e legacy/Bookinsanity Bold.woff2'); font-weight: bold; font-style: normal; } @font-face { font-family: BookSanity; - src: url('../fonts/5e legacy/Bookinsanity Italic.woff2'); + src: url('../../../fonts/5e legacy/Bookinsanity Italic.woff2'); font-weight: normal; font-style: italic; } @font-face { font-family: BookSanity; - src: url('../fonts/5e legacy/Bookinsanity Bold Italic.woff2'); + src: url('../../../fonts/5e legacy/Bookinsanity Bold Italic.woff2'); font-weight: bold; font-style: italic; } @@ -27,19 +27,19 @@ /* Notes and Tables, sans-serif */ @font-face { font-family: ScalySans; - src: url('../fonts/5e legacy/Scaly Sans.woff2'); + src: url('../../../fonts/5e legacy/Scaly Sans.woff2'); font-weight: normal; font-style: normal; } @font-face { font-family: ScalySansSmallCaps; - src: url('../fonts/5e legacy/Scaly Sans Caps.woff2'); + src: url('../../../fonts/5e legacy/Scaly Sans Caps.woff2'); font-weight: normal; font-style: normal; } @font-face { font-family: WalterTurncoat; - src: url('../fonts/5e legacy/WalterTurncoat-Regular.woff2'); + src: url('../../../fonts/5e legacy/WalterTurncoat-Regular.woff2'); font-weight: normal; font-style: normal; } @@ -47,7 +47,7 @@ /* Headers */ @font-face { font-family: MrJeeves; - src: url('../fonts/5e legacy/Mr Eaves Small Caps.woff2'); + src: url('../../../fonts/5e legacy/Mr Eaves Small Caps.woff2'); font-weight: normal; font-style: normal; } @@ -55,7 +55,7 @@ /* Fancy Drop Cap */ @font-face { font-family: Solberry; - src: url('../fonts/5e legacy/Solbera Imitation.woff2'); + src: url('../../../fonts/5e legacy/Solbera Imitation.woff2'); font-weight: normal; font-style: normal; } diff --git a/themes/fonts/5e/fonts.less b/themes/fonts/5e/fonts.less index c7e1ef617..c8ef35c81 100644 --- a/themes/fonts/5e/fonts.less +++ b/themes/fonts/5e/fonts.less @@ -1,25 +1,25 @@ /* Main Font, serif */ @font-face { font-family: BookInsanityRemake; - src: url('../fonts/5e/Bookinsanity.woff2'); + src: url('../../../fonts/5e/Bookinsanity.woff2'); font-weight: normal; font-style: normal; } @font-face { font-family: BookInsanityRemake; - src: url('../fonts/5e/Bookinsanity Bold.woff2'); + src: url('../../../fonts/5e/Bookinsanity Bold.woff2'); font-weight: bold; font-style: normal; } @font-face { font-family: BookInsanityRemake; - src: url('../fonts/5e/Bookinsanity Italic.woff2'); + src: url('../../../fonts/5e/Bookinsanity Italic.woff2'); font-weight: normal; font-style: italic; } @font-face { font-family: BookInsanityRemake; - src: url('../fonts/5e/Bookinsanity Bold Italic.woff2'); + src: url('../../../fonts/5e/Bookinsanity Bold Italic.woff2'); font-weight: bold; font-style: italic; } @@ -27,37 +27,37 @@ /* Notes and Tables, sans-serif */ @font-face { font-family: ScalySansRemake; - src: url('../fonts/5e/Scaly Sans.woff2'); + src: url('../../../fonts/5e/Scaly Sans.woff2'); font-weight: normal; font-style: normal; } @font-face { font-family: ScalySansRemake; - src: url('../fonts/5e/Scaly Sans Bold.woff2'); + src: url('../../../fonts/5e/Scaly Sans Bold.woff2'); font-weight: bold; font-style: normal; } @font-face { font-family: ScalySansRemake; - src: url('../fonts/5e/Scaly Sans Italic.woff2'); + src: url('../../../fonts/5e/Scaly Sans Italic.woff2'); font-weight: normal; font-style: italic; } @font-face { font-family: ScalySansRemake; - src: url('../fonts/5e/Scaly Sans Bold Italic.woff2'); + src: url('../../../fonts/5e/Scaly Sans Bold Italic.woff2'); font-weight: bold; font-style: italic; } @font-face { font-family: ScalySansSmallCapsRemake; - src: url('../fonts/5e/Scaly Sans Caps.woff2'); + src: url('../../../fonts/5e/Scaly Sans Caps.woff2'); font-weight: normal; font-style: normal; } @font-face { font-family: WalterTurncoat; - src: url('../fonts/5e/WalterTurncoat-Regular.woff2'); + src: url('../../../fonts/5e/WalterTurncoat-Regular.woff2'); font-weight: normal; font-style: normal; } @@ -65,7 +65,7 @@ /* Headers */ @font-face { font-family: MrEavesRemake; - src: url('../fonts/5e/Mr Eaves Small Caps.woff2'); + src: url('../../../fonts/5e/Mr Eaves Small Caps.woff2'); font-weight: normal; font-style: normal; } @@ -73,7 +73,7 @@ /* Fancy Drop Cap */ @font-face { font-family: SolberaImitationRemake; //Tweaked 5e version - src: url('../fonts/5e/Solbera Imitation Tweak.woff2'); + src: url('../../../fonts/5e/Solbera Imitation Tweak.woff2'); font-weight: normal; font-style: normal; } diff --git a/themes/fonts/Journal/FrederickaTheGreat-Regular.woff2 b/themes/fonts/Journal/FrederickaTheGreat-Regular.woff2 new file mode 100644 index 000000000..92f13f25b Binary files /dev/null and b/themes/fonts/Journal/FrederickaTheGreat-Regular.woff2 differ diff --git a/themes/fonts/Journal/LICENSE - PermanentMarker.txt b/themes/fonts/Journal/LICENSE - PermanentMarker.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/themes/fonts/Journal/LICENSE - PermanentMarker.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/themes/fonts/Journal/PermanentMarker-Regular.woff2 b/themes/fonts/Journal/PermanentMarker-Regular.woff2 new file mode 100644 index 000000000..6defcd122 Binary files /dev/null and b/themes/fonts/Journal/PermanentMarker-Regular.woff2 differ diff --git a/themes/fonts/Journal/ReenieBeanie-Regular.woff2 b/themes/fonts/Journal/ReenieBeanie-Regular.woff2 new file mode 100644 index 000000000..470a16032 Binary files /dev/null and b/themes/fonts/Journal/ReenieBeanie-Regular.woff2 differ diff --git a/themes/fonts/Journal/fonts.less b/themes/fonts/Journal/fonts.less new file mode 100644 index 000000000..703b594ba --- /dev/null +++ b/themes/fonts/Journal/fonts.less @@ -0,0 +1,58 @@ +/* Main Font, serif */ +@font-face { + font-family: ReenieBeanie; + src: url('../../../fonts/Journal/ReenieBeanie-Regular.woff2'); + font-weight: normal; + font-style: normal; +} + +/* Notes and Tables, sans-serif */ +@font-face { + font-family: PermanentMarker; + src: url('../../../fonts/Journal/PermanentMarker-Regular.woff2'); + 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 { + font-family: FrederickaTheGreat; + src: url('../../../fonts/Journal/FrederickaTheGreat-Regular.woff2'); + font-weight: normal; + font-style: normal; +} + +/* Cover Page */ +@font-face { + font-family: NodestoCapsCondensed; + src: url('../fonts/5e/Nodesto Caps Condensed.woff2'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: NodestoCapsCondensed; + src: url('../fonts/5e/Nodesto Caps Condensed Bold.woff2'); + font-weight: bold; + font-style: normal; +} + +@font-face { + font-family: NodestoCapsCondensed; + src: url('../fonts/5e/Nodesto Caps Condensed Italic.woff2'); + font-weight: normal; + font-style: italic; +} + +@font-face { + font-family: NodestoCapsCondensed; + src: url('../fonts/5e/Nodesto Caps Condensed Bold Italic.woff2'); + font-weight: bold; + font-style: italic; +} diff --git a/themes/themes.json b/themes/themes.json new file mode 100644 index 000000000..0d28c7394 --- /dev/null +++ b/themes/themes.json @@ -0,0 +1,40 @@ +{ + "Legacy": { + "5ePHB": { + "name": "5e PHB", + "renderer": "legacy", + "baseTheme": false, + "path": "5ePHB" + } + }, + "V3": { + "5eDMG": { + "name": "5e DMG", + "renderer": "V3", + "baseTheme": "5ePHB", + "baseSnippets": "5ePHB", + "path": "5eDMG" + }, + "5ePHB": { + "name": "5e PHB", + "renderer": "V3", + "baseTheme": false, + "baseSnippets": false, + "path": "5ePHB" + }, + "Blank": { + "name": "Blank", + "renderer": "V3", + "baseTheme": false, + "baseSnippets": false, + "path": "Blank" + }, + "Journal": { + "name": "Journal", + "renderer": "V3", + "baseTheme": false, + "baseSnippets": "5ePHB", + "path": "Journal" + } + } +} \ No newline at end of file