diff --git a/.circleci/config.yml b/.circleci/config.yml
index 3c48e7d34..461a0dfa6 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -48,7 +48,7 @@ jobs:
- image: cimg/node:16.11.0
working_directory: ~/homebrewery
- parallelism: 4
+ parallelism: 1
steps:
- attach_workspace:
@@ -61,15 +61,15 @@ jobs:
- run:
name: Test - Basic
command: npm run test:basic
- - run:
- name: Test - Coverage
- command: npm run test:coverage
- run:
name: Test - Mustache Spans
- command: npm run test:mustache-span
+ command: npm run test:mustache-syntax
- run:
name: Test - Routes
command: npm run test:route
+ - run:
+ name: Test - Coverage
+ command: npm run test:coverage
workflows:
build_and_test:
diff --git a/.eslintrc.js b/.eslintrc.js
index bc8b5c8cd..74e7bb660 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -11,11 +11,11 @@ module.exports = {
browser : true,
node : true
},
- plugins : ['react'],
+ plugins : ['react', 'jest'],
rules : {
/** Errors **/
'camelcase' : ['error', { properties: 'never' }],
- 'func-style' : ['error', 'expression', { allowArrowFunctions: true }],
+ //'func-style' : ['error', 'expression', { allowArrowFunctions: true }],
'no-array-constructor' : 'error',
'no-iterator' : 'error',
'no-nested-ternary' : 'error',
@@ -24,6 +24,7 @@ module.exports = {
'react/jsx-no-bind' : ['error', { allowArrowFunctions: true }],
'react/jsx-uses-react' : 'error',
'react/prefer-es6-class' : ['error', 'never'],
+ 'jest/valid-expect' : ['error', { maxArgs: 3 }],
/** Warnings **/
'max-lines' : ['warn', {
diff --git a/.stylelintrc.json b/.stylelintrc.json
new file mode 100644
index 000000000..207dfda62
--- /dev/null
+++ b/.stylelintrc.json
@@ -0,0 +1,48 @@
+{
+ "extends": [
+ "stylelint-config-recess-order",
+ "stylelint-config-recommended"],
+ "plugins": [
+ "stylelint-stylistic",
+ "./stylelint_plugins/declaration-colon-align.js",
+ "./stylelint_plugins/declaration-colon-min-space-before",
+ "./stylelint_plugins/declaration-block-multi-line-min-declarations"
+ ],
+ "customSyntax": "postcss-less",
+ "rules": {
+ "no-descending-specificity" : null,
+ "at-rule-no-unknown" : null,
+ "function-no-unknown" : null,
+ "font-family-no-missing-generic-family-keyword" : null,
+ "font-weight-notation" : "named-where-possible",
+ "font-family-name-quotes" : "always-unless-keyword",
+ "stylistic/indentation" : "tab",
+ "no-duplicate-selectors" : true,
+ "stylistic/color-hex-case" : "upper",
+ "color-hex-length" : "long",
+ "stylistic/selector-combinator-space-after" : "always",
+ "stylistic/selector-combinator-space-before" : "always",
+ "stylistic/selector-attribute-operator-space-before" : "never",
+ "stylistic/selector-attribute-operator-space-after" : "never",
+ "stylistic/selector-attribute-brackets-space-inside" : "never",
+ "selector-attribute-quotes" : "always",
+ "selector-pseudo-element-colon-notation" : "double",
+ "stylistic/selector-pseudo-class-parentheses-space-inside" : "never",
+ "stylistic/block-opening-brace-space-before" : "always",
+ "naturalcrit/declaration-colon-min-space-before" : 1,
+ "stylistic/declaration-block-trailing-semicolon" : "always",
+ "stylistic/declaration-colon-space-after" : "always",
+ "stylistic/number-leading-zero" : "always",
+ "function-url-quotes" : ["always", { "except": ["empty"] }],
+ "function-url-scheme-disallowed-list" : ["data","http"],
+ "comment-whitespace-inside" : "always",
+ "stylistic/string-quotes" : "single",
+ "stylistic/media-feature-range-operator-space-before" : "always",
+ "stylistic/media-feature-range-operator-space-after" : "always",
+ "stylistic/media-feature-parentheses-space-inside" : "never",
+ "stylistic/media-feature-colon-space-before" : "always",
+ "stylistic/media-feature-colon-space-after" : "always",
+ "naturalcrit/declaration-colon-align" : true,
+ "naturalcrit/declaration-block-multi-line-min-declarations": 1
+ }
+}
diff --git a/Dockerfile b/Dockerfile
index 33adea2b8..82b13ac86 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM node:16.11-alpine
+FROM node:18-alpine
RUN apk --no-cache add git
ENV NODE_ENV=docker
@@ -10,11 +10,11 @@ WORKDIR /usr/src/app
# This improves caching so we don't have to download the dependencies every time the code changes
COPY package.json ./
# --ignore-scripts tells yarn not to run postbuild. We run it explicitly later
-RUN yarn install --ignore-scripts
+RUN npm install --ignore-scripts
# Bundle app source and build application
COPY . .
-RUN yarn build
+RUN npm run build
EXPOSE 8000
-CMD [ "yarn", "start" ]
+CMD [ "npm", "start" ]
diff --git a/changelog.md b/changelog.md
index 10899a485..626a992d9 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,4 +1,23 @@
```css
+.beta {
+ color : white;
+ padding : 4px 6px;
+ line-height : 1em;
+ background : grey;
+ border-radius : 12px;
+ font-family : monospace;
+ font-size : 10px;
+ font-weight : 800;
+ margin-top : -5px;
+ margin-bottom : -5px;
+}
+
+.fac {
+ height: 1em;
+ line-height: 2em;
+ margin-bottom: -0.05cm
+}
+
h5 {
font-size: .35cm !important;
}
@@ -61,17 +80,226 @@ pre {
## changelog
For a full record of development, visit our [Github Page](https://github.com/naturalcrit/homebrewery).
+### Thursday 17/08/2023 - v3.9.2
+{{taskList
+
+##### Calculuschild
+
+* [x] Fix links to certain old Google Drive files
+
+Fixes issue [#2917](https://github.com/naturalcrit/homebrewery/issues/2917)
+
+##### G-Ambatte
+
+* [x] Menus now open on click, and internally consistent
+
+Fixes issue [#2702](https://github.com/naturalcrit/homebrewery/issues/2702), [#2782](https://github.com/naturalcrit/homebrewery/issues/2782)
+
+* [x] Add smarter footer snippet
+
+Fixes issue [#2289](https://github.com/naturalcrit/homebrewery/issues/2289)
+
+* [x] Add sanitization in Style editor
+
+Fixes issue [#1437](https://github.com/naturalcrit/homebrewery/issues/1437)
+
+* [x] Rework class table snippets to remove unnecessary randomness
+
+Fixes issue [#2964](https://github.com/naturalcrit/homebrewery/issues/2964)
+
+* [x] Add User Page link to Google Drive file for file owners, add icons for additional storage locations
+
+Fixes issue [#2954](https://github.com/naturalcrit/homebrewery/issues/2954)
+
+* [x] Add default save location selection to Account Page
+
+Fixes issue [#2943](https://github.com/naturalcrit/homebrewery/issues/2943)
+
+##### 5e-Cleric
+
+* [x] Exclude cover pages from Table of Content generation (editing on mobile is still not recommended)
+
+Fixes issue [#2920](https://github.com/naturalcrit/homebrewery/issues/2920)
+
+##### Gazook89
+
+* [x] Adjustments to improve mobile viewing
+
+}}
+
+### Wednesday 28/06/2023 - v3.9.1
+{{taskList
+
+##### G-Ambatte
+
+* [x] Better error pages with more useful information
+
+Fixes issue [#1924](https://github.com/naturalcrit/homebrewery/issues/1924)
+}}
+
+### Friday 02/06/2023 - v3.9.0
+{{taskList
+
+##### Calculuschild
+
+* [x] Fix some files not showing up on userpage when user has a large number of brews in Google Drive
+
+Fixes issue [#2408](https://github.com/naturalcrit/homebrewery/issues/2408)
+
+* [x] Pressing tab now indents with spaces instead of tab character; fixes several issues with Markdown lists
+
+Fixes issues [#2092](https://github.com/naturalcrit/homebrewery/issues/2092), [#1556](https://github.com/naturalcrit/homebrewery/issues/1556)
+
+* [x] Rename `naturalCritLogo.svg` to `naturalCritLogoRed.svg`. Those using the {{beta BETA}} coverPage snippet may need to update that text to make the NaturalCrit logo appear again.
+
+##### G-Ambatte
+
+* [x] Fix strange animation of image masks
+
+Fixes issue [#2790](https://github.com/naturalcrit/homebrewery/issues/2790)
+
+##### 5e-Cleric
+
+* [x] New {{openSans **PHB → {{fac,book-part-cover}} PART COVER PAGE** }} snippet for V3!
+
+* [x] New {{openSans **PHB → {{fac,book-back-cover}} BACK COVER PAGE** }} snippet for V3! (Thanks to /u/Kaiburr_Kath-Hound on Reddit for providing some of these resources!)
+
+* [x] New {{openSans **TEXT EDITOR → {{fas,fa-bars}} INDEX** }} snippet for V3!
+
+* [x] Fix highlighting of curly braces inside comments
+
+Fixes issue [#2784](https://github.com/naturalcrit/homebrewery/issues/2784)
+}}
+
+### Wednesday 12/04/2023 - v3.8.0
+{{taskList
+
+##### calculuschild
+
+* [x] Rename `{{coverPage}}` to `{{frontCover}}`. Those using this {{beta BETA}} feature will need to update that text to make the cover page appear again.
+
+* [x] Several background fixes to test scripts
+
+##### Jeddai
+
+* [X] Add content negotiation to exclude image requests from our API calls
+
+Fixes issue [#2595](https://github.com/naturalcrit/homebrewery/issues/2595)
+
+##### G-Ambatte
+
+* [x] Update server build scripts to fix Admin page
+
+Fixes issues [#2657](https://github.com/naturalcrit/homebrewery/issues/2657)
+
+* [x] Fix internal links inside `<\div>` blocks not receiving the `target=_self` attribute
+
+Fixes issues [#2680](https://github.com/naturalcrit/homebrewery/issues/2680)
+
+* [x] See brew details on `/share` pages by clicking the brew title (author, last update, tags, etc.)
+
+Fixes issues [#1679](https://github.com/naturalcrit/homebrewery/issues/1679)
+
+* [x] Add local Windows install script via Chocolatey
+
+##### 5e-Cleric
+
+* [x] New {{openSans **TABLES → {{fas,fa-language}} RUNE TABLE**}} snippets for V3. Adds an alphabetic script translation table.
+
+* [x] New {{openSans **IMAGES → {{fac,mask-center}} WATERCOLOR CENTER** }} snippets for V3, which adds a stylish watercolor texture to the center of your images!
+
+* [x] New {{openSans **PHB → {{fac,book-inside-cover}} INSIDE COVER PAGE** }} snippet for V3! (Thanks to /u/Kaiburr_Kath-Hound on Reddit for providing some of these resources!)
+
+* [x] Add some missing characters {{font-family:scalySansRemake Ñ ñ ç Ç Ý ý # ^ ¿ ' " ¡ ·}} to the "scalySansRemake" font in V3.
+
+Fixes issues [#2280](https://github.com/naturalcrit/homebrewery/issues/2280)
+
+##### Gazook89
+
+* [x] Add "Language" selector in {{fa,fa-info-circle}} **Properties** menu. Sets the HTML Lang attribute for your brew to better handle hyphenation or spellcheck.
+
+Fixes issues [#1343](https://github.com/naturalcrit/homebrewery/issues/1343)
+
+* [x] Fix a crash when multiple `{injection}` tags appear in sequence
+
+Fixes issues [#2712](https://github.com/naturalcrit/homebrewery/issues/2712)
+
+##### MichielDeMey
+
+* [x] Remove all-caps display on Account button since usernames are case-sensitive.
+
+Fixes issues [#2731](https://github.com/naturalcrit/homebrewery/issues/2731)
+
+}}
+
+\page
+
+### Monday 13/03/2023 - v3.7.2
+{{taskList
+
+##### Calculuschild
+
+* [x] Fix wide Monster Stat Blocks not spanning columns on Legacy
+}}
+
+### Thursday 09/03/2023 - v3.7.1
+{{taskList
+
+##### Lucastucious (new contributor!)
+
+* [x] Changed `filter: drop-shadow` to `box-shadow` on text boxes, making PDF text selectable
+
+Fixes issues [#1569](https://github.com/naturalcrit/homebrewery/issues/1569)
+
+{{note
+**NOTE:** If you create your PDF on a computer with an old version of Mac Preview (v10 or older) you may see shadows appear as solid gray.
+}}
+
+##### MichielDeMey
+
+* [x] Updated the Google Drive icon
+* [x] Backend fix to unit tests failing intermittently
+
+##### Calculuschild
+
+* [x] Fix PDF pixelation on CoverPage text outlines
+}}
+
+### Tuesday 28/02/2023 - v3.7.0
+{{taskList
+
+{{note
+**NOTE:** Some new snippets will now show a {{beta BETA}} tag. Feel free to use them, but be aware we may change how they work depending on your feedback.
+}}
+
+##### Calculuschild
+
+* [x] New {{openSans **IMAGES → WATERCOLOR EDGE** {{fac,mask-edge}} }} and {{openSans **WATERCOLOR CORNER** {{fac,mask-corner}} }} snippets for V3, which adds a stylish watercolor texture to the edge of your images! (Thanks to /u/flamableconcrete on Reddit for providing these image masks!)
+
+* [x] Fix site not displaying on iOS devices
+
+##### 5e-Cleric
+
+* [x] New {{openSans **PHB → COVER PAGE** {{fac,book-front-cover}} }} snippet for V3, which adds a stylish coverpage to your brew! (Thanks to /u/Kaiburr_Kath-Hound on Reddit for providing some of these resources!)
+
+##### MichielDeMey (new contribuor!)
+
+* [x] Fix typo in testing scripts
+* [x] Fix "mug" image not using HTTPS
+
+Fixes issues [#2687](https://github.com/naturalcrit/homebrewery/issues/2687)
+}}
+
### Saturday 18/02/2023 - v3.6.1
{{taskList
##### G-Ambatte
-* [x] Fix users not being removed from Authors list correctly
+* [x] Fix users not being removed from Authors list
Fixes issues [#2674](https://github.com/naturalcrit/homebrewery/issues/2674)
}}
-
-### Friday 23/01/2023 - v3.6.0
+### Monday 23/01/2023 - v3.6.0
{{taskList
##### calculuschild
@@ -96,6 +324,8 @@ Fixes issues [#2583](https://github.com/naturalcrit/homebrewery/issues/2583)
* [x] Fix cloned brews inheriting the parent view count
}}
+\page
+
### Friday 23/12/2022 - v3.5.0
{{taskList
@@ -109,8 +339,6 @@ Fixes issues [#2583](https://github.com/naturalcrit/homebrewery/issues/2583)
Fixes issues [#1987](https://github.com/naturalcrit/homebrewery/issues/1987)
}}
-\page
-
### Saturday 10/12/2022 - v3.4.2
{{taskList
diff --git a/client/components/combobox.jsx b/client/components/combobox.jsx
new file mode 100644
index 000000000..a6e699dcf
--- /dev/null
+++ b/client/components/combobox.jsx
@@ -0,0 +1,129 @@
+const React = require('react');
+const createClass = require('create-react-class');
+const _ = require('lodash');
+const cx = require('classnames');
+require('./combobox.less');
+
+const Combobox = createClass({
+ displayName : 'Combobox',
+ getDefaultProps : function() {
+ return {
+ className : '',
+ trigger : 'hover',
+ default : '',
+ placeholder : '',
+ autoSuggest : {
+ clearAutoSuggestOnClick : true,
+ suggestMethod : 'includes',
+ filterOn : [] // should allow as array to filter on multiple attributes, or even custom filter
+ },
+ };
+ },
+ getInitialState : function() {
+ return {
+ showDropdown : false,
+ value : '',
+ options : [...this.props.options],
+ inputFocused : false
+ };
+ },
+ componentDidMount : function() {
+ if(this.props.trigger == 'click')
+ document.addEventListener('click', this.handleClickOutside);
+ this.setState({
+ value : this.props.default
+ });
+ },
+ 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,
+ inputFocused : this.props.autoSuggest.clearAutoSuggestOnClick ? show : false
+ });
+ },
+ handleInput : function(e){
+ e.persist();
+ this.setState({
+ value : e.target.value,
+ inputFocused : false
+ }, ()=>{
+ this.props.onEntry(e);
+ });
+ },
+ handleSelect : function(e){
+ this.setState({
+ value : e.currentTarget.getAttribute('data-value')
+ }, ()=>{this.props.onSelect(this.state.value);});
+ ;
+ },
+ renderTextInput : function(){
+ return (
+
{this.handleDropdown(true);} : undefined}
+ onClick= {this.props.trigger == 'click' ? ()=>{this.handleDropdown(true);} : undefined}>
+ this.handleInput(e)}
+ value={this.state.value || ''}
+ placeholder={this.props.placeholder}
+ onBlur={(e)=>{
+ if(!e.target.checkValidity()){
+ this.setState({
+ value : this.props.default
+ }, ()=>this.props.onEntry(e));
+ }
+ }}
+ />
+
+ );
+ },
+ renderDropdown : function(dropdownChildren){
+ if(!this.state.showDropdown) return null;
+ if(this.props.autoSuggest && !this.state.inputFocused){
+ const suggestMethod = this.props.autoSuggest.suggestMethod;
+ const filterOn = _.isString(this.props.autoSuggest.filterOn) ? [this.props.autoSuggest.filterOn] : this.props.autoSuggest.filterOn;
+ const filteredArrays = filterOn.map((attr)=>{
+ const children = dropdownChildren.filter((item)=>{
+ if(suggestMethod === 'includes'){
+ return item.props[attr]?.toLowerCase().includes(this.state.value.toLowerCase());
+ } else if(suggestMethod === 'startsWith'){
+ return item.props[attr]?.toLowerCase().startsWith(this.state.value.toLowerCase());
+ }
+ });
+ return children;
+ });
+ dropdownChildren = _.uniq(filteredArrays.flat(1));
+ }
+
+ return (
+
+ {dropdownChildren}
+
+ );
+ },
+ render : function () {
+ const dropdownChildren = this.state.options.map((child, i)=>{
+ const clone = React.cloneElement(child, { onClick: (e)=>this.handleSelect(e) });
+ return clone;
+ });
+ return (
+ {this.handleDropdown(false);} : undefined}>
+ {this.renderTextInput()}
+ {this.renderDropdown(dropdownChildren)}
+
+ );
+ }
+});
+
+module.exports = Combobox;
diff --git a/client/components/combobox.less b/client/components/combobox.less
new file mode 100644
index 000000000..3810a874e
--- /dev/null
+++ b/client/components/combobox.less
@@ -0,0 +1,50 @@
+.dropdown-container {
+ position:relative;
+ input {
+ width: 100%;
+ }
+ .dropdown-options {
+ position:absolute;
+ background-color: white;
+ z-index: 100;
+ width: 100%;
+ border: 1px solid gray;
+ overflow-y: auto;
+ max-height: 200px;
+
+ &::-webkit-scrollbar {
+ width: 14px;
+ }
+ &::-webkit-scrollbar-track {
+ background: #ffffff;
+ }
+ &::-webkit-scrollbar-thumb {
+ background-color: #949494;
+ border-radius: 10px;
+ border: 3px solid #ffffff;
+ }
+
+ .item {
+ position:relative;
+ font-size: 11px;
+ font-family: Open Sans;
+ padding: 5px;
+ cursor: default;
+ margin: 0 3px;
+ //border-bottom: 1px solid darkgray;
+ &:hover {
+ filter: brightness(120%);
+ background-color: rgb(163, 163, 163);
+ }
+ .detail {
+ width:100%;
+ text-align: left;
+ color: rgb(124, 124, 124);
+ font-style:italic;
+ font-size: 9px;
+ }
+ }
+
+ }
+
+}
diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx
index f8a5fce0a..51921c8ca 100644
--- a/client/homebrew/brewRenderer/brewRenderer.jsx
+++ b/client/homebrew/brewRenderer/brewRenderer.jsx
@@ -27,6 +27,7 @@ const BrewRenderer = createClass({
style : '',
renderer : 'legacy',
theme : '5ePHB',
+ lang : '',
errors : []
};
},
@@ -107,6 +108,12 @@ const BrewRenderer = createClass({
return false;
},
+ sanitizeScriptTags : function(content) {
+ return content
+ .replace(/';
- const rendered = Markdown.render(source);
- expect(rendered).toMatch('<script></script>');
-});
-
test('Processes the markdown within an HTML block if its just a class wrapper', function() {
const source = '*Bold text*
';
const rendered = Markdown.render(source);
expect(rendered).toBe('');
});
+
+test('Check markdown is using the custom renderer; specifically that it adds target=_self attribute to internal links in HTML blocks', function() {
+ const source = '[Has _self Attribute?](#p1)
';
+ const rendered = Markdown.render(source);
+ expect(rendered).toBe('');
+});
diff --git a/tests/markdown/mustache-span.test.js b/tests/markdown/mustache-span.test.js
deleted file mode 100644
index 6d249ebcb..000000000
--- a/tests/markdown/mustache-span.test.js
+++ /dev/null
@@ -1,128 +0,0 @@
-/* eslint-disable max-lines */
-
-const Markdown = require('naturalcrit/markdown.js');
-
-test('Renders a mustache span with text only', function() {
- const source = '{{ text}}';
- const rendered = Markdown.render(source);
- expect(rendered).toBe('text ');
-});
-
-test('Renders a mustache span with text only, but with spaces', function() {
- const source = '{{ this is a text}}';
- const rendered = Markdown.render(source);
- expect(rendered).toBe('this is a text ');
-});
-
-test('Renders an empty mustache span', function() {
- const source = '{{}}';
- const rendered = Markdown.render(source);
- expect(rendered).toBe(' ');
-});
-
-test('Renders a mustache span with just a space', function() {
- const source = '{{ }}';
- const rendered = Markdown.render(source);
- expect(rendered).toBe(' ');
-});
-
-test('Renders a mustache span with a few spaces only', function() {
- const source = '{{ }}';
- const rendered = Markdown.render(source);
- expect(rendered).toBe(' ');
-});
-
-test('Renders a mustache span with text and class', function() {
- const source = '{{my-class text}}';
- const rendered = Markdown.render(source);
- // FIXME: why do we have those two extra spaces after closing "?
- expect(rendered).toBe('text ');
-});
-
-test('Renders a mustache span with text and two classes', function() {
- const source = '{{my-class,my-class2 text}}';
- const rendered = Markdown.render(source);
- // FIXME: why do we have those two extra spaces after closing "?
- expect(rendered).toBe('text ');
-});
-
-test('Renders a mustache span with text with spaces and class', function() {
- const source = '{{my-class this is a text}}';
- const rendered = Markdown.render(source);
- // FIXME: why do we have those two extra spaces after closing "?
- expect(rendered).toBe('this is a text ');
-});
-
-test('Renders a mustache span with text and id', function() {
- const source = '{{#my-span text}}';
- const rendered = Markdown.render(source);
- // FIXME: why do we have that one extra space after closing "?
- expect(rendered).toBe('text ');
-});
-
-test('Renders a mustache span with text and two ids', function() {
- const source = '{{#my-span,#my-favorite-span text}}';
- const rendered = Markdown.render(source);
- // FIXME: do we need to report an error here somehow?
- expect(rendered).toBe('text ');
-});
-
-test('Renders a mustache span with text and css property', function() {
- const source = '{{color:red text}}';
- const rendered = Markdown.render(source);
- expect(rendered).toBe('text ');
-});
-
-test('Renders a mustache span with text and two css properties', function() {
- const source = '{{color:red,padding:5px text}}';
- const rendered = Markdown.render(source);
- expect(rendered).toBe('text ');
-});
-
-test('Renders a mustache span with text and css property which contains quotes', function() {
- const source = '{{font:"trebuchet ms" text}}';
- const rendered = Markdown.render(source);
- // FIXME: is it correct to remove quotes surrounding css property value?
- expect(rendered).toBe('text ');
-});
-
-test('Renders a mustache span with text and two css properties which contains quotes', function() {
- const source = '{{font:"trebuchet ms",padding:"5px 10px" text}}';
- const rendered = Markdown.render(source);
- expect(rendered).toBe('text ');
-});
-
-
-test('Renders a mustache span with text with quotes and css property which contains quotes', function() {
- const source = '{{font:"trebuchet ms" text "with quotes"}}';
- const rendered = Markdown.render(source);
- expect(rendered).toBe('text “with quotes” ');
-});
-
-test('Renders a mustache span with text, id, class and a couple of css properties', function() {
- const source = '{{pen,#author,color:orange,font-family:"trebuchet ms" text}}';
- const rendered = Markdown.render(source);
- expect(rendered).toBe('text ');
-});
-
-// TODO: add tests for ID with accordance to CSS spec:
-//
-// From https://drafts.csswg.org/selectors/#id-selectors:
-//
-// > An ID selector consists of a “number sign” (U+0023, #) immediately followed by the ID value, which must be a CSS identifier.
-//
-// From: https://www.w3.org/TR/CSS21/syndata.html#value-def-identifier:
-//
-// > In CSS, identifiers (including element names, classes, and IDs in selectors) can contain only the characters [a-zA-Z0-9]
-// > and ISO 10646 characters U+00A0 and higher, plus the hyphen (-) and the underscore (_);
-// > they cannot start with a digit, two hyphens, or a hyphen followed by a digit.
-// > Identifiers can also contain escaped characters and any ISO 10646 character as a numeric code (see next item).
-// > For instance, the identifier "B&W?" may be written as "B\&W\?" or "B\26 W\3F".
-// > Note that Unicode is code-by-code equivalent to ISO 10646 (see [UNICODE] and [ISO10646]).
-
-// TODO: add tests for class with accordance to CSS spec:
-//
-// From: https://drafts.csswg.org/selectors/#class-html:
-//
-// > The class selector is given as a full stop (. U+002E) immediately followed by an identifier.
-
diff --git a/tests/markdown/mustache-syntax.test.js b/tests/markdown/mustache-syntax.test.js
new file mode 100644
index 000000000..d9e1ce6f9
--- /dev/null
+++ b/tests/markdown/mustache-syntax.test.js
@@ -0,0 +1,375 @@
+/* eslint-disable max-lines */
+
+const dedent = require('dedent-tabs').default;
+const Markdown = require('naturalcrit/markdown.js');
+
+// Marked.js adds line returns after closing tags on some default tokens.
+// This removes those line returns for comparison sake.
+String.prototype.trimReturns = function(){
+ return this.replace(/\r?\n|\r/g, '');
+};
+
+// Adding `.failing()` method to `describe` or `it` will make failing tests "pass" as long as they continue to fail.
+// Remove the `.failing()` method once you have fixed the issue.
+
+describe('Inline: When using the Inline syntax {{ }}', ()=>{
+ it.failing('Renders a mustache span with text only', function() {
+ const source = '{{ text}}';
+ const rendered = Markdown.render(source);
+ // FIXME: adds extra \s after class names
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text ');
+ });
+
+ it.failing('Renders a mustache span with text only, but with spaces', function() {
+ const source = '{{ this is a text}}';
+ const rendered = Markdown.render(source);
+ // FIXME: adds extra \s after class names
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('this is a text ');
+ });
+
+ it.failing('Renders an empty mustache span', function() {
+ const source = '{{}}';
+ const rendered = Markdown.render(source);
+ // FIXME: adds extra \s after class names
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(' ');
+ });
+
+ it.failing('Renders a mustache span with just a space', function() {
+ const source = '{{ }}';
+ const rendered = Markdown.render(source);
+ // FIXME: adds extra \s after class names
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(' ');
+ });
+
+ it.failing('Renders a mustache span with a few spaces only', function() {
+ const source = '{{ }}';
+ const rendered = Markdown.render(source);
+ // FIXME: adds extra \s after class names
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(' ');
+ });
+
+ it.failing('Renders a mustache span with text and class', function() {
+ const source = '{{my-class text}}';
+ const rendered = Markdown.render(source);
+ // FIXME: adds two extra \s before closing `>` in opening tag.
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text ');
+ });
+
+ it.failing('Renders a mustache span with text and two classes', function() {
+ const source = '{{my-class,my-class2 text}}';
+ const rendered = Markdown.render(source);
+ // FIXME: adds two extra \s before closing `>` in opening tag.
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text ');
+ });
+
+ it.failing('Renders a mustache span with text with spaces and class', function() {
+ const source = '{{my-class this is a text}}';
+ const rendered = Markdown.render(source);
+ // FIXME: adds two extra \s before closing `>` in opening tag
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('this is a text ');
+ });
+
+ it.failing('Renders a mustache span with text and id', function() {
+ const source = '{{#my-span text}}';
+ const rendered = Markdown.render(source);
+ // FIXME: adds extra \s before closing `>` in opening tag, and another after class names
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text ');
+ });
+
+ it.failing('Renders a mustache span with text and two ids', function() {
+ const source = '{{#my-span,#my-favorite-span text}}';
+ const rendered = Markdown.render(source);
+ // FIXME: adds extra \s before closing `>` in opening tag, and another after class names
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text ');
+ });
+
+ it.failing('Renders a mustache span with text and css property', function() {
+ const source = '{{color:red text}}';
+ const rendered = Markdown.render(source);
+ // FIXME: adds extra \s after class names
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text ');
+ });
+
+ it.failing('Renders a mustache span with text and two css properties', function() {
+ const source = '{{color:red,padding:5px text}}';
+ const rendered = Markdown.render(source);
+ // FIXME: adds extra \s after class names
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text ');
+ });
+
+ it.failing('Renders a mustache span with text and css property which contains quotes', function() {
+ const source = '{{font-family:"trebuchet ms" text}}';
+ const rendered = Markdown.render(source);
+ // FIXME: adds extra \s after class names
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text ');
+ });
+
+ it.failing('Renders a mustache span with text and two css properties which contains quotes', function() {
+ const source = '{{font-family:"trebuchet ms",padding:"5px 10px" text}}';
+ const rendered = Markdown.render(source);
+ // FIXME: adds extra \s after class names
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text ');
+ });
+
+
+ it.failing('Renders a mustache span with text with quotes and css property which contains quotes', function() {
+ const source = '{{font-family:"trebuchet ms" text "with quotes"}}';
+ const rendered = Markdown.render(source);
+ // FIXME: adds extra \s after class names
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text “with quotes” ');
+ });
+
+ it('Renders a mustache span with text, id, class and a couple of css properties', function() {
+ const source = '{{pen,#author,color:orange,font-family:"trebuchet ms" text}}';
+ const rendered = Markdown.render(source);
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text ');
+ });
+});
+
+// BLOCK SYNTAX
+
+describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{
+ it.failing('Renders a div with text only', function() {
+ const source = dedent`{{
+ text
+ }}`;
+ const rendered = Markdown.render(source).trimReturns();
+ // FIXME: adds extra \s after class names
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(``);
+ });
+
+ it.failing('Renders an empty div', function() {
+ const source = dedent`{{
+
+ }}`;
+ const rendered = Markdown.render(source).trimReturns();
+ // FIXME: adds extra \s after class names
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`
`);
+ });
+
+ it('Renders a single paragraph with opening and closing brackets', function() {
+ const source = dedent`{{
+ }}`;
+ const rendered = Markdown.render(source).trimReturns();
+ // this actually renders in HB as '{{ }}'...
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`{{}}
`);
+ });
+
+ it.failing('Renders a div with a single class', function() {
+ const source = dedent`{{cat
+
+ }}`;
+ const rendered = Markdown.render(source).trimReturns();
+ // FIXME: adds two extra \s before closing `>` in opening tag
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`
`);
+ });
+
+ it.failing('Renders a div with a single class and text', function() {
+ const source = dedent`{{cat
+ Sample text.
+ }}`;
+ const rendered = Markdown.render(source).trimReturns();
+ // FIXME: adds two extra \s before closing `>` in opening tag
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(``);
+ });
+
+ it.failing('Renders a div with two classes and text', function() {
+ const source = dedent`{{cat,dog
+ Sample text.
+ }}`;
+ const rendered = Markdown.render(source).trimReturns();
+ // FIXME: adds two extra \s before closing `>` in opening tag
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(``);
+ });
+
+ it.failing('Renders a div with a style and text', function() {
+ const source = dedent`{{color:red
+ Sample text.
+ }}`;
+ const rendered = Markdown.render(source).trimReturns();
+ // FIXME: adds two extra \s before closing `>` in opening tag
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(``);
+ });
+
+ it.failing('Renders a div with a class, style and text', function() {
+ const source = dedent`{{cat,color:red
+ Sample text.
+ }}`;
+ const rendered = Markdown.render(source).trimReturns();
+ // FIXME: adds extra \s after the class attribute
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(``);
+ });
+
+ it('Renders a div with an ID, class, style and text (different order)', function() {
+ const source = dedent`{{color:red,cat,#dog
+ Sample text.
+ }}`;
+ const rendered = Markdown.render(source).trimReturns();
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(``);
+ });
+
+ it.failing('Renders a div with a single ID', function() {
+ const source = dedent`{{#cat,#dog
+ Sample text.
+ }}`;
+ const rendered = Markdown.render(source).trimReturns();
+ // FIXME: adds extra \s before closing `>` in opening tag, and another after class names
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(``);
+ });
+});
+
+// MUSTACHE INJECTION SYNTAX
+
+describe('Injection: When an injection tag follows an element', ()=>{
+ // FIXME: Most of these fail because injections currently replace attributes, rather than append to. Or just minor extra whitespace issues.
+ describe('and that element is an inline-block', ()=>{
+ it.failing('Renders a span "text" with no injection', function() {
+ const source = '{{ text}}{}';
+ const rendered = Markdown.render(source);
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text ');
+ });
+
+ it.failing('Renders a span "text" with injected Class name', function() {
+ const source = '{{ text}}{ClassName}';
+ const rendered = Markdown.render(source);
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text ');
+ });
+
+ it.failing('Renders a span "text" with injected style', function() {
+ const source = '{{ text}}{color:red}';
+ const rendered = Markdown.render(source);
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text ');
+ });
+
+ it.failing('Renders a span "text" with two injected styles', function() {
+ const source = '{{ text}}{color:red,background:blue}';
+ const rendered = Markdown.render(source);
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text ');
+ });
+
+ it.failing('Renders an emphasis element with injected Class name', function() {
+ const source = '*emphasis*{big}';
+ const rendered = Markdown.render(source).trimReturns();
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('emphasis
');
+ });
+
+ it.failing('Renders a code element with injected style', function() {
+ const source = '`code`{background:gray}';
+ const rendered = Markdown.render(source).trimReturns();
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('code
');
+ });
+
+ it.failing('Renders an image element with injected style', function() {
+ const source = '![alt text](http://i.imgur.com/hMna6G0.png){position:absolute}';
+ const rendered = Markdown.render(source).trimReturns();
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('
');
+ });
+
+ it.failing('Renders an element modified by only the first of two consecutive injections', function() {
+ const source = '{{ text}}{color:red}{background:blue}';
+ const rendered = Markdown.render(source).trimReturns();
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text {background:blue}
');
+ });
+ });
+
+ describe('and that element is a block', ()=>{
+ it.failing('renders a div "text" with no injection', function() {
+ const source = '{{\ntext\n}}\n{}';
+ const rendered = Markdown.render(source).trimReturns();
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('');
+ });
+
+ it.failing('renders a div "text" with injected Class name', function() {
+ const source = '{{\ntext\n}}\n{ClassName}';
+ const rendered = Markdown.render(source).trimReturns();
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('');
+ });
+
+ it.failing('renders a div "text" with injected style', function() {
+ const source = '{{\ntext\n}}\n{color:red}';
+ const rendered = Markdown.render(source).trimReturns();
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('');
+ });
+
+ it.failing('renders a div "text" with two injected styles', function() {
+ const source = dedent`{{
+ text
+ }}
+ {color:red,background:blue}`;
+ const rendered = Markdown.render(source).trimReturns();
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('');
+ });
+
+ it.failing('renders an h2 header "text" with injected class name', function() {
+ const source = dedent`## text
+ {ClassName}`;
+ const rendered = Markdown.render(source).trimReturns();
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text ');
+ });
+
+ it.failing('renders a table with injected class name', function() {
+ const source = dedent`| Experience Points | Level |
+ |:------------------|:-----:|
+ | 0 | 1 |
+ | 300 | 2 |
+
+ {ClassName}`;
+ const rendered = Markdown.render(source).trimReturns();
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`Experience Points Level 0 1 300 2
`);
+ });
+
+ // it('renders a list with with a style injected into the tag', function() {
+ // const source = dedent`- Cursed Ritual of Bad Hair
+ // - Eliminate Vindictiveness in Gym Teacher
+ // - Ultimate Rite of the Confetti Angel
+ // - Dark Chant of the Dentists
+ // - Divine Spell of Crossdressing
+ // {color:red}`;
+ // const rendered = Markdown.render(source).trimReturns();
+ // expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`...`); // FIXME: expect this to be injected into ? Currently injects into last
+ // });
+
+ it.failing('renders an h2 header "text" with injected class name, and "secondInjection" as regular text on the next line.', function() {
+ const source = dedent`## text
+ {ClassName}
+ {secondInjection}`;
+ const rendered = Markdown.render(source).trimReturns();
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text {secondInjection}
');
+ });
+
+ it.failing('renders a div nested into another div, the inner with class=innerDiv and the other class=outerDiv', function() {
+ const source = dedent`{{
+ outer text
+ {{
+ inner text
+ }}
+ {innerDiv}
+ }}
+ {outerDiv}`;
+ const rendered = Markdown.render(source).trimReturns();
+ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('');
+ });
+ });
+});
+
+
+// TODO: add tests for ID with accordance to CSS spec:
+//
+// From https://drafts.csswg.org/selectors/#id-selectors:
+//
+// > An ID selector consists of a “number sign” (U+0023, #) immediately followed by the ID value, which must be a CSS identifier.
+//
+// From: https://www.w3.org/TR/CSS21/syndata.html#value-def-identifier:
+//
+// > In CSS, identifiers (including element names, classes, and IDs in selectors) can contain only the characters [a-zA-Z0-9]
+// > and ISO 10646 characters U+00A0 and higher, plus the hyphen (-) and the underscore (_);
+// > they cannot start with a digit, two hyphens, or a hyphen followed by a digit.
+// > Identifiers can also contain escaped characters and any ISO 10646 character as a numeric code (see next item).
+// > For instance, the identifier "B&W?" may be written as "B\&W\?" or "B\26 W\3F".
+// > Note that Unicode is code-by-code equivalent to ISO 10646 (see [UNICODE] and [ISO10646]).
+
+// TODO: add tests for class with accordance to CSS spec:
+//
+// From: https://drafts.csswg.org/selectors/#class-html:
+//
+// > The class selector is given as a full stop (. U+002E) immediately followed by an identifier.
diff --git a/themes/Legacy/5ePHB/snippets/tableOfContents.gen.js b/themes/Legacy/5ePHB/snippets/tableOfContents.gen.js
index 4082ac4ef..40d64af22 100644
--- a/themes/Legacy/5ePHB/snippets/tableOfContents.gen.js
+++ b/themes/Legacy/5ePHB/snippets/tableOfContents.gen.js
@@ -47,8 +47,8 @@ const getTOC = (pages)=>{
return res;
};
-module.exports = function(brew){
- const pages = brew.text.split('\\page');
+module.exports = function(props){
+ const pages = props.brew.text.split('\\page');
const TOC = getTOC(pages);
const markdown = _.reduce(TOC, (r, g1, idx1)=>{
r.push(`- **[${idx1 + 1} ${g1.title}](#p${g1.page})**`);
diff --git a/themes/Legacy/5ePHB/style.less b/themes/Legacy/5ePHB/style.less
index 2544ff77d..fa7539f16 100644
--- a/themes/Legacy/5ePHB/style.less
+++ b/themes/Legacy/5ePHB/style.less
@@ -1,499 +1,498 @@
-@layer Legacy_5ePHB {
- @import (less) './themes/fonts/5e legacy/fonts.less';
- @import (less) './themes/assets/assets.less';
- @import (less) './themes/phb.depricated.less';
- //Colors
- @background : #EEE5CE; // Light parchment
- @noteGreen : #e0e5c1; // Pastel green
- @headerUnderline : #c9ad6a; // Gold
- @horizontalRule : #9c2b1b; // Maroon
- @headerText : #58180D; // Dark maroon
- @monsterStatBackground : #FDF1DC; // Lighter parchment
- @captionText : #766649; // Brown
- @page { margin: 0; }
- body {
- counter-reset : phb-page-numbers;
- }
- *{
- -webkit-print-color-adjust : exact;
- }
- .useSansSerif(){
+@import (less) './themes/fonts/5e legacy/fonts.less';
+@import (less) './themes/assets/assets.less';
+@import (less) './themes/phb.depricated.less';
+//Colors
+@background : #EEE5CE; // Light parchment
+@noteGreen : #e0e5c1; // Pastel green
+@headerUnderline : #c9ad6a; // Gold
+@horizontalRule : #9c2b1b; // Maroon
+@headerText : #58180D; // Dark maroon
+@monsterStatBackground : #FDF1DC; // Lighter parchment
+@captionText : #766649; // Brown
+@page { margin: 0; }
+body {
+ counter-reset : phb-page-numbers;
+}
+*{
+ -webkit-print-color-adjust : exact;
+}
+.useSansSerif(){
+ font-family : ScalySans;
+ em{
font-family : ScalySans;
- em{
- font-family : ScalySans;
- font-style : italic;
+ font-style : italic;
+ }
+ strong{
+ font-family : ScalySans;
+ font-weight : 800;
+ letter-spacing : -0.02em;
+ }
+}
+.useColumns(@multiplier : 1){
+ column-count : 2;
+ column-fill : auto;
+ column-gap : 1cm;
+ column-width : 8cm * @multiplier;
+ -webkit-column-count : 2;
+ -moz-column-count : 2;
+ -webkit-column-width : 8cm * @multiplier;
+ -moz-column-width : 8cm * @multiplier;
+ -webkit-column-gap : 1cm;
+ -moz-column-gap : 1cm;
+}
+.phb{
+ .useColumns();
+ counter-increment : phb-page-numbers;
+ position : relative;
+ z-index : 15;
+ box-sizing : border-box;
+ overflow : hidden;
+ height : 279.4mm;
+ width : 215.9mm;
+ padding : 1.0cm 1.7cm;
+ padding-bottom : 1.5cm;
+ background-color : @background;
+ background-image : @backgroundImage;
+ font-family : BookSanity;
+ font-size : 0.317cm;
+ text-rendering : optimizeLegibility;
+ page-break-before : always;
+ page-break-after : always;
+ contain : size;
+ //*****************************
+ // * BASE
+ // *****************************/
+ p{
+ padding-bottom : 0.8em;
+ line-height : 1.269em;
+ &+p{
+ margin-top : -0.8em;
}
- strong{
- font-family : ScalySans;
- font-weight : 800;
- letter-spacing : -0.02em;
+ }
+ ul{
+ margin-bottom : 0.8em;
+ padding-left : 1.4em;
+ line-height : 1.269em;
+ list-style-position : outside;
+ list-style-type : disc;
+ }
+ ol{
+ margin-bottom : 0.8em;
+ padding-left : 1.4em;
+ line-height : 1.269em;
+ list-style-position : outside;
+ list-style-type : decimal;
+ }
+ //Indents after p or lists
+ p+p, ul+p, ol+p{
+ text-indent : 1em;
+ }
+ img{
+ z-index : -1;
+ }
+ strong{
+ font-weight : bold;
+ letter-spacing : 0.03em;
+ }
+ em{
+ font-style : italic;
+ }
+ sup{
+ vertical-align : super;
+ font-size : smaller;
+ line-height : 0;
+ }
+ sub{
+ vertical-align : sub;
+ font-size : smaller;
+ line-height : 0;
+ }
+ //*****************************
+ // * HEADERS
+ // *****************************/
+ h1,h2,h3,h4{
+ margin-top : 0.2em;
+ margin-bottom : 0.2em;
+ font-family : MrJeeves;
+ font-weight : 800;
+ color : @headerText;
+ }
+ h1{
+ column-span : all;
+ font-size : 0.987cm;
+ -webkit-column-span : all;
+ -moz-column-span : all;
+ &+p::first-letter{
+ float : left;
+ font-family : Solberry;
+ font-size : 10em;
+ color : #222;
+ line-height : 0.795em;
}
}
- .useColumns(@multiplier : 1){
- column-count : 2;
- column-fill : auto;
- column-gap : 1cm;
- column-width : 8cm * @multiplier;
- -webkit-column-count : 2;
- -moz-column-count : 2;
- -webkit-column-width : 8cm * @multiplier;
- -moz-column-width : 8cm * @multiplier;
- -webkit-column-gap : 1cm;
- -moz-column-gap : 1cm;
- }
- .phb{
- .useColumns();
- counter-increment : phb-page-numbers;
- position : relative;
- z-index : 15;
- box-sizing : border-box;
- overflow : hidden;
- height : 279.4mm;
- width : 215.9mm;
- padding : 1.0cm 1.7cm;
- padding-bottom : 1.5cm;
- background-color : @background;
- background-image : @backgroundImage;
- font-family : BookSanity;
- font-size : 0.317cm;
- text-rendering : optimizeLegibility;
- page-break-before : always;
- page-break-after : always;
- contain : size;
- //*****************************
- // * BASE
- // *****************************/
- p{
- padding-bottom : 0.8em;
- line-height : 1.269em;
- &+p{
- margin-top : -0.8em;
+ h2{
+ font-size : 0.705cm;
+ }
+ h3{
+ font-size : 0.529cm;
+ border-bottom : 2px solid @headerUnderline;
+ }
+ h4{
+ margin-bottom : 0.00em;
+ font-size : 0.458cm;
+ }
+ h5{
+ margin-bottom : 0.2em;
+ font-family : ScalySansSmallCaps;
+ font-size : 0.423cm;
+ font-weight : 900;
+ }
+ //*****************************
+ // * TABLE
+ // *****************************/
+ table{
+ .useSansSerif();
+ width : 100%;
+ margin-bottom : 1em;
+ font-size : 10pt;
+ thead{
+ display: table-row-group;
+ font-weight : 800;
+ th{
+ vertical-align : bottom;
+ padding-bottom : 0.3em;
+ padding-right : 0.1em;
+ padding-left : 0.1em;
}
}
- ul{
- margin-bottom : 0.8em;
- padding-left : 1.4em;
- line-height : 1.269em;
- list-style-position : outside;
- list-style-type : disc;
- }
- ol{
- margin-bottom : 0.8em;
- padding-left : 1.4em;
- line-height : 1.269em;
- list-style-position : outside;
- list-style-type : decimal;
- }
- //Indents after p or lists
- p+p, ul+p, ol+p{
- text-indent : 1em;
- }
- img{
- z-index : -1;
- }
- strong{
- font-weight : bold;
- letter-spacing : 0.03em;
- }
- em{
- font-style : italic;
- }
- sup{
- vertical-align : super;
- font-size : smaller;
- line-height : 0;
- }
- sub{
- vertical-align : sub;
- font-size : smaller;
- line-height : 0;
- }
- //*****************************
- // * HEADERS
- // *****************************/
- h1,h2,h3,h4{
- margin-top : 0.2em;
- margin-bottom : 0.2em;
- font-family : MrJeeves;
- font-weight : 800;
- color : @headerText;
- }
- h1{
- column-span : all;
- font-size : 0.987cm;
- -webkit-column-span : all;
- -moz-column-span : all;
- &+p::first-letter{
- float : left;
- font-family : Solberry;
- font-size : 10em;
- color : #222;
- line-height : 0.795em;
+ tbody{
+ tr{
+ td{
+ padding : 0.3em 0.1em;
+ }
+ &:nth-child(odd){
+ background-color : @noteGreen;
+ }
}
}
+ }
+ //*****************************
+ // * NOTE
+ // *****************************/
+ blockquote{
+ .useSansSerif();
+ box-sizing : border-box;
+ margin-bottom : 1em;
+ padding : 5px 10px;
+ background-color : @noteGreen;
+ border-style : solid;
+ border-width : 11px;
+ border-image : @noteBorderImage 11;
+ border-image-outset : 9px 0px;
+ box-shadow : 1px 4px 14px #888;
+ p, ul{
+ font-size : 0.352cm;
+ line-height : 1.083em;
+ }
+ }
+ //If a note starts a column, give it space at the top to render border
+ pre+blockquote, h2+blockquote, h3+blockquote, h4+blockquote, h5+blockquote {
+ margin-top : 13px;
+ }
+ //*****************************
+ // * MONSTER STAT BLOCK
+ // *****************************/
+ hr+blockquote{
+ position : relative;
+ padding-top : 15px;
+ background-color : @monsterStatBackground;
+ border-style : solid;
+ border-width : 10px;
+ border-image : @monsterBorderImageLegacy 10;
h2{
- font-size : 0.705cm;
+ margin-top : -8px;
+ margin-bottom : 0px;
+ &+p{
+ padding-bottom : 0px;
+ }
}
h3{
- font-size : 0.529cm;
- border-bottom : 2px solid @headerUnderline;
- }
- h4{
- margin-bottom : 0.00em;
- font-size : 0.458cm;
+ font-family : ScalySans;
+ font-weight : 400;
+ border-bottom : 1px solid @headerText;
}
- h5{
- margin-bottom : 0.2em;
- font-family : ScalySansSmallCaps;
- font-size : 0.423cm;
- font-weight : 900;
+ hr+ul{
+ color : @headerText;
}
- //*****************************
- // * TABLE
- // *****************************/
- table{
+ ul{
.useSansSerif();
- width : 100%;
- margin-bottom : 1em;
- font-size : 10pt;
- thead{
- display: table-row-group;
- font-weight : 800;
- th{
- vertical-align : bottom;
- padding-bottom : 0.3em;
- padding-right : 0.1em;
- padding-left : 0.1em;
- }
- }
+ padding-left : 1em;
+ font-size : 0.352cm;
+ }
+ // Monster Ability table
+ hr+table{
+ margin : 0;
+ background-color : transparent;
+ border-style : none;
+ border-image : none;
tbody{
- tr{
- td{
- padding : 0.3em 0.1em;
- }
- &:nth-child(odd){
- background-color : @noteGreen;
- }
+ tr:nth-child(odd), tr:nth-child(even){
+ background-color : transparent;
}
}
}
- //*****************************
- // * NOTE
- // *****************************/
- blockquote{
- .useSansSerif();
- box-sizing : border-box;
- margin-bottom : 1em;
- padding : 5px 10px;
- background-color : @noteGreen;
- border-style : solid;
- border-width : 11px;
- border-image : @noteBorderImage 11;
- border-image-outset : 9px 0px;
- box-shadow : 1px 4px 14px #888;
- p, ul{
- font-size : 0.352cm;
- line-height : 1.083em;
- }
+ table{
+ color : @headerText;
}
- //If a note starts a column, give it space at the top to render border
- pre+blockquote, h2+blockquote, h3+blockquote, h4+blockquote, h5+blockquote {
- margin-top : 13px;
+ p+p{
+ margin-top : 0em;
+ padding-bottom : 0.5em;
+ text-indent : 0em;
}
- //*****************************
- // * MONSTER STAT BLOCK
- // *****************************/
- hr+blockquote{
- position : relative;
- padding-top : 15px;
- background-color : @monsterStatBackground;
- border-style : solid;
- border-width : 10px;
- border-image : @monsterBorderImageLegacy 10;
- h2{
- margin-top : -8px;
- margin-bottom : 0px;
- &+p{
- padding-bottom : 0px;
- }
- }
- h3{
- font-family : ScalySans;
- font-weight : 400;
- border-bottom : 1px solid @headerText;
- }
- hr+ul{
- color : @headerText;
- }
- ul{
- .useSansSerif();
- padding-left : 1em;
- font-size : 0.352cm;
- }
- // Monster Ability table
- hr+table{
- margin : 0;
- background-color : transparent;
- border-style : none;
- border-image : none;
- tbody{
- tr:nth-child(odd), tr:nth-child(even){
- background-color : transparent;
- }
- }
- }
- table{
- color : @headerText;
- }
- p+p{
- margin-top : 0em;
- padding-bottom : 0.5em;
- text-indent : 0em;
- }
- //Triangle dividers
- hr{
- visibility : visible;
- height : 6px;
- margin : 4px 0px;
- background-image : @redTriangleImage;
- background-size : 100% 100%;
- border : none;
- }
- }
- //Full Width
- hr+hr+blockquote{
- .useColumns(0.96);
+ //Triangle dividers
+ hr{
+ visibility : visible;
+ height : 6px;
+ margin : 4px 0px;
+ background-image : @redTriangleImage;
+ background-size : 100% 100%;
+ border : none;
}
- //*****************************
- // * FOOTER
- // *****************************/
+ }
+ //Full Width
+ hr+hr+blockquote{
+ .useColumns(0.96);
+ column-fill : balance;
+ }
+ //*****************************
+ // * FOOTER
+ // *****************************/
+ &:after{
+ content : "";
+ position : absolute;
+ bottom : 0px;
+ left : 0px;
+ z-index : 100;
+ height : 50px;
+ width : 100%;
+ background-image : @footerAccentImage;
+ background-size : cover;
+ }
+ &:nth-child(even){
&:after{
- content : "";
- position : absolute;
- bottom : 0px;
- left : 0px;
- z-index : 100;
- height : 50px;
- width : 100%;
- background-image : @footerAccentImage;
- background-size : cover;
- }
- &:nth-child(even){
- &:after{
- transform : scaleX(-1);
- }
- .pageNumber{
- left : 2px;
- }
- .footnote{
- left : 80px;
- text-align : left;
- }
+ transform : scaleX(-1);
}
.pageNumber{
- position : absolute;
- right : 2px;
- bottom : 22px;
- width : 50px;
- font-size : 0.9em;
- color : #c9ad6a;
- text-align : center;
- &.auto::after {
- content : counter(phb-page-numbers);
- }
+ left : 2px;
}
.footnote{
- position : absolute;
- right : 80px;
- bottom : 32px;
- z-index : 150;
- width : 200px;
- font-size : 0.8em;
- color : #c9ad6a;
- text-align : right;
- }
- //*****************************
- // * EXTRAS
- // *****************************/
- hr{
- visibility : hidden;
- margin : 0px;
- }
- //Modified unorder list, used in spells
- hr+ul{
- margin-bottom : 0.5em;
- padding-left : 1em;
- text-indent : -1em;
- list-style-type : none;
- }
- //Column Break
- pre, code{
- visibility : hidden;
- -webkit-column-break-after : always;
- break-after : always;
- -moz-column-break-after : always;
- }
- //Avoid breaking up
- p,blockquote,table{
- z-index : 15;
- -webkit-column-break-inside : avoid;
- page-break-inside : avoid;
- break-inside : avoid;
- }
- //Better spacing for spell blocks
- h4+p+hr+ul{
- margin-top : -0.5em
- }
- //Text indent right after table
- table+p{
- text-indent : 1em;
- }
- // 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;
+ left : 80px;
+ text-align : left;
}
}
- //*****************************
- // * SPELL LIST
- // *****************************/
- .phb .spellList{
- .useSansSerif();
- column-count : 4;
- column-span : all;
- -webkit-column-span : all;
- -moz-column-span : all;
- ul+h5{
- margin-top : 15px;
- }
- p, ul{
- font-size : 0.352cm;
- line-height : 1.263em;
- }
- 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;
+ .pageNumber{
+ position : absolute;
+ right : 2px;
+ bottom : 22px;
+ width : 50px;
+ font-size : 0.9em;
+ color : #c9ad6a;
+ text-align : center;
+ &.auto::after {
+ content : counter(phb-page-numbers);
}
}
- //*****************************
- // * WIDE
- // *****************************/
- .phb .wide{
- column-span : all;
- -webkit-column-span : all;
- -moz-column-span : all;
+ .footnote{
+ position : absolute;
+ right : 80px;
+ bottom : 32px;
+ z-index : 150;
+ width : 200px;
+ font-size : 0.8em;
+ color : #c9ad6a;
+ text-align : right;
}
//*****************************
- // * CLASS TABLE
+ // * EXTRAS
// *****************************/
- .phb .classTable{
- margin-top : 25px;
- margin-bottom : 40px;
- border-collapse : separate;
- background-color : white;
- border : initial;
- border-style : solid;
- border-image-outset : 25px 17px;
- border-image-repeat : stretch;
- border-image-slice : 150 200 150 200;
- border-image-source : @frameBorderImage;
- border-image-width : 47px;
- h5{
- margin-bottom : 10px;
- }
+ hr{
+ visibility : hidden;
+ margin : 0px;
}
- //************************************
- // * DESCRIPTIVE TEXT BOX
- // ************************************/
- .phb .descriptive{
- margin-bottom : 1em;
- background-color : #faf7ea;
- font-family : ScalySans;
- border-style : solid;
- border-width : 7px;
- border-image : @descriptiveBoxImage 12 stretch;
- border-image-outset : 4px;
- box-shadow : 0px 0px 6px #faf7ea;
- p{
- display : block;
- padding-bottom : 0px;
- line-height : 1.47em;
- }
- p + p {
- padding-top : .8em;
- }
- em {
- font-family : ScalySans;
- font-style : italic;
- }
- strong {
- font-family : ScalySans;
- font-weight : 800;
- letter-spacing : -0.02em;
- }
+ //Modified unorder list, used in spells
+ hr+ul{
+ margin-bottom : 0.5em;
+ padding-left : 1em;
+ text-indent : -1em;
+ list-style-type : none;
}
- .phb pre+.descriptive{
- margin-top : 8px;
+ //Column Break
+ pre, code{
+ visibility : hidden;
+ -webkit-column-break-after : always;
+ break-after : always;
+ -moz-column-break-after : always;
}
-
- //*****************************
- // * ARTIST CREDIT BLOCK
- // *****************************/
- .phb {
- .artist {
- position : absolute;
- text-align : center;
- font-family : WalterTurncoat;
- font-size : 0.27cm;
- color : @captionText;
- p, p + p {
- margin : unset;
- text-indent : unset;
- line-height : 0.941em;
- }
- h5 {
- font-size : 1.3em;
- font-family : WalterTurncoat;
- }
- a{
- color : inherit;
- text-decoration : unset;
- &:hover {
- text-decoration : underline;
- }
- }
- }
+ //Avoid breaking up
+ p,blockquote,table{
+ z-index : 15;
+ -webkit-column-break-inside : avoid;
+ page-break-inside : avoid;
+ break-inside : avoid;
}
- //*****************************
- // * TABLE OF CONTENTS
- // *****************************/
- .phb .toc{
+ //Better spacing for spell blocks
+ h4+p+hr+ul{
+ margin-top : -0.5em
+ }
+ //Text indent right after table
+ table+p{
+ text-indent : 1em;
+ }
+ // 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;
+ }
+}
+//*****************************
+// * SPELL LIST
+// *****************************/
+.phb .spellList{
+ .useSansSerif();
+ column-count : 4;
+ column-span : all;
+ -webkit-column-span : all;
+ -moz-column-span : all;
+ ul+h5{
+ margin-top : 15px;
+ }
+ p, ul{
+ font-size : 0.352cm;
+ line-height : 1.263em;
+ }
+ 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
+// *****************************/
+.phb .wide{
+ column-span : all;
+ -webkit-column-span : all;
+ -moz-column-span : all;
+}
+//*****************************
+// * CLASS TABLE
+// *****************************/
+.phb .classTable{
+ margin-top : 25px;
+ margin-bottom : 40px;
+ border-collapse : separate;
+ background-color : white;
+ border : initial;
+ border-style : solid;
+ border-image-outset : 25px 17px;
+ border-image-repeat : stretch;
+ border-image-slice : 150 200 150 200;
+ border-image-source : @frameBorderImage;
+ border-image-width : 47px;
+ h5{
+ margin-bottom : 10px;
+ }
+}
+//************************************
+// * DESCRIPTIVE TEXT BOX
+// ************************************/
+.phb .descriptive{
+ margin-bottom : 1em;
+ background-color : #faf7ea;
+ font-family : ScalySans;
+ border-style : solid;
+ border-width : 7px;
+ border-image : @descriptiveBoxImage 12 stretch;
+ border-image-outset : 4px;
+ box-shadow : 0px 0px 6px #faf7ea;
+ p{
+ display : block;
+ padding-bottom : 0px;
+ line-height : 1.47em;
+ }
+ p + p {
+ padding-top : .8em;
+ }
+ em {
+ font-family : ScalySans;
+ font-style : italic;
+ }
+ strong {
+ font-family : ScalySans;
+ font-weight : 800;
+ letter-spacing : -0.02em;
+ }
+}
+.phb pre+.descriptive{
+ margin-top : 8px;
+}
+
+//*****************************
+// * ARTIST CREDIT BLOCK
+// *****************************/
+.phb {
+ .artist {
+ position : absolute;
+ text-align : center;
+ font-family : WalterTurncoat;
+ font-size : 0.27cm;
+ color : @captionText;
+ p, p + p {
+ margin : unset;
+ text-indent : unset;
+ line-height : 0.941em;
+ }
+ h5 {
+ font-size : 1.3em;
+ font-family : WalterTurncoat;
+ }
a{
- color : black;
- text-decoration : none;
- &:hover{
+ color : inherit;
+ text-decoration : unset;
+ &:hover {
text-decoration : underline;
}
}
- ul{
- padding-left : 0;
- list-style-type : none;
- }
- &>ul>li{
- margin-bottom : 10px;
+ }
+}
+//*****************************
+// * TABLE OF CONTENTS
+// *****************************/
+.phb .toc{
+ -webkit-column-break-inside : avoid;
+ page-break-inside : avoid;
+ break-inside : avoid;
+ a{
+ color : black;
+ text-decoration : none;
+ &:hover{
+ text-decoration : underline;
}
}
+ ul{
+ padding-left : 0;
+ list-style-type : none;
+ }
+ &>ul>li{
+ margin-bottom : 10px;
+ }
}
diff --git a/themes/V3/5eDMG/style.less b/themes/V3/5eDMG/style.less
index 02056a34b..ffc73d992 100644
--- a/themes/V3/5eDMG/style.less
+++ b/themes/V3/5eDMG/style.less
@@ -1,21 +1,28 @@
-@layer V3_5eDMG {
- :root {
- //Colors
- --HB_Color_Accent : #EBCEC3; // Salmon
- --HB_Color_Footnotes : #5C5C5C; // Dark gray
- }
+@import (less) './themes/assets/assets.less';
+
+:root {
+ //Colors
+ --HB_Color_Accent : #EBCEC3; // Salmon
+ --HB_Color_Footnotes : #5C5C5C; // Dark gray
+}
- .page {
- background-image : url(/assets/DMG_background.png);
- background-size : cover;
+.page {
+ background-image : url(/assets/DMG_background.png);
+ background-size : cover;
- &:after {
- background-image : url(/assets/DMG_footerAccent.png);
- height: 58px;
- }
+ &:after {
+ background-image : url(/assets/DMG_footerAccent.png);
+ height: 58px;
+ }
- .footnote {
- bottom : 40px;
- }
+ .footnote {
+ bottom : 40px;
}
}
+
+.page:has(.partCover) {
+
+ .partCover {
+ background-image: @partCoverHeaderDMG;
+ }
+}
\ No newline at end of file
diff --git a/themes/V3/5ePHB/snippets.js b/themes/V3/5ePHB/snippets.js
index bea2a1da3..506bc0edd 100644
--- a/themes/V3/5ePHB/snippets.js
+++ b/themes/V3/5ePHB/snippets.js
@@ -3,9 +3,11 @@
const MagicGen = require('./snippets/magic.gen.js');
const ClassTableGen = require('./snippets/classtable.gen.js');
const MonsterBlockGen = require('./snippets/monsterblock.gen.js');
+const scriptGen = require('./snippets/script.gen.js');
const ClassFeatureGen = require('./snippets/classfeature.gen.js');
const CoverPageGen = require('./snippets/coverpage.gen.js');
const TableOfContentsGen = require('./snippets/tableOfContents.gen.js');
+const indexGen = require('./snippets/index.gen.js');
const dedent = require('dedent-tabs').default;
@@ -17,20 +19,16 @@ module.exports = [
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
+ },
+ {
+ name : 'Index',
+ icon : 'fas fa-bars',
+ gen : indexGen,
+ experimental : true
}
]
},
@@ -169,9 +167,28 @@ module.exports = [
gen : MonsterBlockGen.monster('monster,frame,wide', 4),
},
{
- name : 'Cover Page',
- icon : 'fas fa-file-word',
- gen : CoverPageGen,
+ name : 'Front Cover Page',
+ icon : 'fac book-front-cover',
+ gen : CoverPageGen.front,
+ experimental : true
+ },
+ {
+ name : 'Inside Cover Page',
+ icon : 'fac book-inside-cover',
+ gen : CoverPageGen.inside,
+ experimental : true
+ },
+ {
+ name : 'Part Cover Page',
+ icon : 'fac book-part-cover',
+ gen : CoverPageGen.part,
+ experimental : true
+ },
+ {
+ name : 'Back Cover Page',
+ icon : 'fac book-back-cover',
+ gen : CoverPageGen.back,
+ experimental : true
},
{
name : 'Magic Item',
@@ -189,7 +206,7 @@ module.exports = [
}}
\n`;
},
- },
+ }
]
},
@@ -203,35 +220,75 @@ module.exports = [
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 : 'Class Tables',
+ icon : 'fas fa-table',
+ gen : ClassTableGen.full('classTable,frame,decoration,wide'),
+ subsnippets : [
+ {
+ name : 'Martial Class Table',
+ icon : 'fas fa-table',
+ gen : ClassTableGen.non('classTable,frame,decoration'),
+ },
+ {
+ name : 'Martial Class Table (unframed)',
+ icon : 'fas fa-border-none',
+ gen : ClassTableGen.non('classTable'),
+ },
+ {
+ name : 'Full Caster Class Table',
+ icon : 'fas fa-table',
+ gen : ClassTableGen.full('classTable,frame,decoration,wide'),
+ },
+ {
+ name : 'Full Caster Class Table (unframed)',
+ icon : 'fas fa-border-none',
+ gen : ClassTableGen.full('classTable,wide'),
+ },
+ {
+ name : 'Half Caster Class Table',
+ icon : 'fas fa-list-alt',
+ gen : ClassTableGen.half('classTable,frame,decoration,wide'),
+ },
+ {
+ name : 'Half Caster Class Table (unframed)',
+ icon : 'fas fa-border-none',
+ gen : ClassTableGen.half('classTable,wide'),
+ },
+ {
+ name : 'Third Caster Spell Table',
+ icon : 'fas fa-border-all',
+ gen : ClassTableGen.third('classTable,frame,decoration'),
+ },
+ {
+ name : 'Third Caster Spell Table (unframed)',
+ icon : 'fas fa-border-none',
+ gen : ClassTableGen.third('classTable'),
+ }
+ ]
},
{
- name : '1/3 Class Table',
- icon : 'fas fa-border-all',
- gen : ClassTableGen.third('classTable,frame'),
+ name : 'Rune Table',
+ icon : 'fas fa-language',
+ gen : scriptGen.dwarvish,
+ experimental : true,
+ subsnippets : [
+ {
+ name : 'Dwarvish',
+ icon : 'fac davek',
+ gen : scriptGen.dwarvish,
+ },
+ {
+ name : 'Elvish',
+ icon : 'fac rellanic',
+ gen : scriptGen.elvish,
+ },
+ {
+ name : 'Draconic',
+ icon : 'fac iokharic',
+ gen : scriptGen.draconic,
+ },
+ ]
},
- {
- name : '1/3 Class Table (unframed)',
- icon : 'fas fa-border-none',
- gen : ClassTableGen.third('classTable'),
- }
]
},
diff --git a/themes/V3/5ePHB/snippets/classtable.gen.js b/themes/V3/5ePHB/snippets/classtable.gen.js
index c1f6254f9..1fdff036f 100644
--- a/themes/V3/5ePHB/snippets/classtable.gen.js
+++ b/themes/V3/5ePHB/snippets/classtable.gen.js
@@ -1,132 +1,138 @@
const _ = require('lodash');
+const dedent = require('dedent-tabs').default;
const features = [
- 'Astrological Botany',
- 'Biochemical Sorcery',
- 'Civil Divination',
- 'Consecrated Augury',
- 'Demonic Anthropology',
- 'Divinatory Mineralogy',
- 'Exo Interfacer',
- 'Genetic Banishing',
- 'Gunpowder Torturer',
- 'Gunslinger Corruptor',
- 'Hermetic Geography',
- 'Immunological Cultist',
- 'Malefic Chemist',
- 'Mathematical Pharmacy',
- 'Nuclear Biochemistry',
- 'Orbital Gravedigger',
- 'Pharmaceutical Outlaw',
- 'Phased Linguist',
- 'Plasma Gunslinger',
- 'Police Necromancer',
- 'Ritual Astronomy',
- 'Sixgun Poisoner',
- 'Seismological Alchemy',
- 'Spiritual Illusionism',
- 'Statistical Occultism',
- 'Spell Analyst',
- 'Torque Interfacer'
+ 'Astrological Botany', 'Biochemical Sorcery', 'Civil Divination',
+ 'Consecrated Augury', 'Demonic Anthropology', 'Divinatory Mineralogy',
+ 'Exo Interfacer', 'Genetic Banishing', 'Gunpowder Torturer',
+ 'Gunslinger Corruptor', 'Hermetic Geography', 'Immunological Cultist',
+ 'Malefic Chemist', 'Mathematical Pharmacy', 'Nuclear Biochemistry',
+ 'Orbital Gravedigger', 'Pharmaceutical Outlaw', 'Phased Linguist',
+ 'Plasma Gunslinger', 'Police Necromancer', 'Ritual Astronomy',
+ 'Sixgun Poisoner', 'Seismological Alchemy', 'Spiritual Illusionism',
+ 'Statistical Occultism', 'Spell Analyst', 'Torque Interfacer'
+].map((f)=>_.padEnd(f, 21)); // Pad to equal length of 21 chars long
+
+const classnames = [
+ 'Ackerman', 'Berserker-Typist', 'Concierge', 'Fishmonger',
+ 'Haberdasher', 'Manicurist', 'Netrunner', 'Weirkeeper'
];
-const classnames = ['Ackerman', 'Berserker-Typist', 'Concierge', 'Fishmonger',
- 'Haberdasher', 'Manicurist', 'Netrunner', 'Weirkeeper'];
-
-const levels = ['1st', '2nd', '3rd', '4th', '5th',
- '6th', '7th', '8th', '9th', '10th',
- '11th', '12th', '13th', '14th', '15th',
- '16th', '17th', '18th', '19th', '20th'];
-
-const profBonus = [2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6];
-
-const maxes = [4, 3, 3, 3, 3, 2, 2, 1, 1];
-
-const drawSlots = function(Slots, rows, padding){
- let slots = Number(Slots);
- return _.times(rows, function(i){
- const max = maxes[i];
- if(slots < 1) return _.pad('—', padding);
- const res = _.min([max, slots]);
- slots -= res;
- return _.pad(res.toString(), padding);
- }).join(' | ');
-};
-
module.exports = {
- full : function(classes){
- const classname = _.sample(classnames);
-
-
- let cantrips = 3;
- let spells = 1;
- let slots = 2;
- return `{{${classes}\n##### The ${classname}\n` +
- `| Level | Proficiency | Features | Cantrips | Spells | --- Spell Slots Per Spell Level ---|||||||||\n`+
- `| ^| Bonus ^| ^| Known ^| Known ^|1st |2nd |3rd |4th |5th |6th |7th |8th |9th |\n`+
- `|:-----:|:-----------:|:-------------|:--------:|:------:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|\n${
- _.map(levels, function(levelName, level){
- const res = [
- _.pad(levelName, 5),
- _.pad(`+${profBonus[level]}`, 2),
- _.padEnd(_.sample(features), 21),
- _.pad(cantrips.toString(), 8),
- _.pad(spells.toString(), 6),
- drawSlots(slots, 9, 2),
- ].join(' | ');
-
- cantrips += _.random(0, 1);
- spells += _.random(0, 1);
- slots += _.random(0, 2);
-
- return `| ${res} |`;
- }).join('\n')}\n}}\n\n`;
+ non : function(snippetClasses){
+ return dedent`
+ {{${snippetClasses}
+ ##### The ${_.sample(classnames)}
+ | Level | Proficiency Bonus | Features | ${_.sample(features)} |
+ |:-----:|:-----------------:|:---------|:---------------------:|
+ | 1st | +2 | ${_.sample(features)} | 2 |
+ | 2nd | +2 | ${_.sample(features)} | 2 |
+ | 3rd | +2 | ${_.sample(features)} | 3 |
+ | 4th | +2 | ${_.sample(features)} | 3 |
+ | 5th | +3 | ${_.sample(features)} | 3 |
+ | 6th | +3 | ${_.sample(features)} | 4 |
+ | 7th | +3 | ${_.sample(features)} | 4 |
+ | 8th | +3 | ${_.sample(features)} | 4 |
+ | 9th | +4 | ${_.sample(features)} | 4 |
+ | 10th | +4 | ${_.sample(features)} | 4 |
+ | 11th | +4 | ${_.sample(features)} | 4 |
+ | 12th | +4 | ${_.sample(features)} | 5 |
+ | 13th | +5 | ${_.sample(features)} | 5 |
+ | 14th | +5 | ${_.sample(features)} | 5 |
+ | 15th | +5 | ${_.sample(features)} | 5 |
+ | 16th | +5 | ${_.sample(features)} | 5 |
+ | 17th | +6 | ${_.sample(features)} | 6 |
+ | 18th | +6 | ${_.sample(features)} | 6 |
+ | 19th | +6 | ${_.sample(features)} | 6 |
+ | 20th | +6 | ${_.sample(features)} | unlimited |
+ }}\n\n`;
},
- half : function(classes){
- const classname = _.sample(classnames);
-
- let featureScore = 1;
- return `{{${classes}\n##### The ${classname}\n` +
- `| Level | Proficiency Bonus | Features | ${_.pad(_.sample(features), 21)} |\n` +
- `|:-----:|:-----------------:|:---------|:---------------------:|\n${
- _.map(levels, function(levelName, level){
- const res = [
- _.pad(levelName, 5),
- _.pad(`+${profBonus[level]}`, 2),
- _.padEnd(_.sample(features), 23),
- _.pad(`+${featureScore}`, 21),
- ].join(' | ');
-
- featureScore += _.random(0, 1);
-
- return `| ${res} |`;
- }).join('\n')}\n}}\n\n`;
+ full : function(snippetClasses){
+ return dedent`
+ {{${snippetClasses}
+ ##### The ${_.sample(classnames)}
+ | Level | Proficiency | Features | Cantrips | --- Spell Slots Per Spell Level ---|||||||||
+ | ^| Bonus ^| ^| Known ^|1st |2nd |3rd |4th |5th |6th |7th |8th |9th |
+ |:-----:|:-----------:|:-------------|:--------:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|
+ | 1st | +2 | ${_.sample(features)} | 2 | 2 | — | — | — | — | — | — | — | — |
+ | 2nd | +2 | ${_.sample(features)} | 2 | 3 | — | — | — | — | — | — | — | — |
+ | 3rd | +2 | ${_.sample(features)} | 2 | 4 | 2 | — | — | — | — | — | — | — |
+ | 4th | +2 | ${_.sample(features)} | 3 | 4 | 3 | — | — | — | — | — | — | — |
+ | 5th | +3 | ${_.sample(features)} | 3 | 4 | 3 | 2 | — | — | — | — | — | — |
+ | 6th | +3 | ${_.sample(features)} | 3 | 4 | 3 | 3 | — | — | — | — | — | — |
+ | 7th | +3 | ${_.sample(features)} | 3 | 4 | 3 | 3 | 1 | — | — | — | — | — |
+ | 8th | +3 | ${_.sample(features)} | 3 | 4 | 3 | 3 | 2 | — | — | — | — | — |
+ | 9th | +4 | ${_.sample(features)} | 3 | 4 | 3 | 3 | 2 | 1 | — | — | — | — |
+ | 10th | +4 | ${_.sample(features)} | 3 | 4 | 3 | 3 | 2 | 1 | — | — | — | — |
+ | 11th | +4 | ${_.sample(features)} | 4 | 4 | 3 | 3 | 2 | 1 | 1 | — | — | — |
+ | 12th | +4 | ${_.sample(features)} | 4 | 4 | 3 | 3 | 2 | 1 | 1 | — | — | — |
+ | 13th | +5 | ${_.sample(features)} | 4 | 4 | 3 | 3 | 2 | 1 | 1 | 1 | — | — |
+ | 14th | +5 | ${_.sample(features)} | 4 | 4 | 3 | 3 | 2 | 1 | 1 | 1 | — | — |
+ | 15th | +5 | ${_.sample(features)} | 4 | 4 | 3 | 3 | 2 | 1 | 1 | 1 | 1 | — |
+ | 16th | +5 | ${_.sample(features)} | 4 | 4 | 3 | 3 | 2 | 1 | 1 | 1 | 1 | — |
+ | 17th | +6 | ${_.sample(features)} | 4 | 4 | 3 | 3 | 2 | 1 | 1 | 1 | 1 | 1 |
+ | 18th | +6 | ${_.sample(features)} | 4 | 4 | 3 | 3 | 3 | 1 | 1 | 1 | 1 | 1 |
+ | 19th | +6 | ${_.sample(features)} | 4 | 4 | 3 | 3 | 3 | 2 | 2 | 1 | 1 | 1 |
+ | 20th | +6 | ${_.sample(features)} | 4 | 4 | 3 | 3 | 3 | 2 | 2 | 2 | 1 | 1 |
+ }}\n\n`;
},
- third : function(classes){
- const classname = _.sample(classnames);
-
- let cantrips = 3;
- let spells = 1;
- let slots = 2;
- return `{{${classes}\n##### ${classname} Spellcasting\n` +
- `| Class | Cantrips | Spells |--- Spells Slots per Spell Level ---||||\n` +
- `| Level ^| Known ^| Known ^| 1st | 2nd | 3rd | 4th |\n` +
- `|:------:|:--------:|:-------:|:-------:|:-------:|:-------:|:-------:|\n${
- _.map(levels, function(levelName, level){
- const res = [
- _.pad(levelName, 6),
- _.pad(cantrips.toString(), 8),
- _.pad(spells.toString(), 7),
- drawSlots(slots, 4, 7),
- ].join(' | ');
-
- cantrips += _.random(0, 1);
- spells += _.random(0, 1);
- slots += _.random(0, 1);
+ half : function(snippetClasses){
+ return dedent`
+ {{${snippetClasses}
+ ##### The ${_.sample(classnames)}
+ | Level | Proficiency | Features | Spells |--- Spell Slots Per Spell Level ---|||||
+ | ^| Bonus ^| ^| Known ^| 1st | 2nd | 3rd | 4th | 5th |
+ |:-----:|:-----------:|:-------------|:------:|:-----:|:-----:|:-----:|:-----:|:-----:|
+ | 1st | +2 | ${_.sample(features)} | — | — | — | — | — | — |
+ | 2nd | +2 | ${_.sample(features)} | 2 | 2 | — | — | — | — |
+ | 3rd | +2 | ${_.sample(features)} | 3 | 3 | — | — | — | — |
+ | 4th | +2 | ${_.sample(features)} | 3 | 3 | — | — | — | — |
+ | 5th | +3 | ${_.sample(features)} | 4 | 4 | 2 | — | — | — |
+ | 6th | +3 | ${_.sample(features)} | 4 | 4 | 2 | — | — | — |
+ | 7th | +3 | ${_.sample(features)} | 5 | 4 | 3 | — | — | — |
+ | 8th | +3 | ${_.sample(features)} | 5 | 4 | 3 | — | — | — |
+ | 9th | +4 | ${_.sample(features)} | 6 | 4 | 3 | 2 | — | — |
+ | 10th | +4 | ${_.sample(features)} | 6 | 4 | 3 | 2 | — | — |
+ | 11th | +4 | ${_.sample(features)} | 7 | 4 | 3 | 3 | — | — |
+ | 12th | +4 | ${_.sample(features)} | 7 | 4 | 3 | 3 | — | — |
+ | 13th | +5 | ${_.sample(features)} | 8 | 4 | 3 | 3 | 1 | — |
+ | 14th | +5 | ${_.sample(features)} | 8 | 4 | 3 | 3 | 1 | — |
+ | 15th | +5 | ${_.sample(features)} | 9 | 4 | 3 | 3 | 2 | — |
+ | 16th | +5 | ${_.sample(features)} | 9 | 4 | 3 | 3 | 2 | — |
+ | 17th | +6 | ${_.sample(features)} | 10 | 4 | 3 | 3 | 3 | 1 |
+ | 18th | +6 | ${_.sample(features)} | 10 | 4 | 3 | 3 | 3 | 1 |
+ | 19th | +6 | ${_.sample(features)} | 11 | 4 | 3 | 3 | 3 | 2 |
+ | 20th | +6 | ${_.sample(features)} | 11 | 4 | 3 | 3 | 3 | 2 |
+ }}\n\n`;
+ },
- return `| ${res} |`;
- }).join('\n')}\n}}\n\n`;
+ third : function(snippetClasses){
+ return dedent`
+ {{${snippetClasses}
+ ##### ${_.sample(classnames)} Spellcasting
+ | Level | Cantrips | Spells |--- Spells Slots per Spell Level ---||||
+ | ^| Known ^| Known ^| 1st | 2nd | 3rd | 4th |
+ |:-----:|:--------:|:------:|:-------:|:-------:|:-------:|:-------:|
+ | 3rd | 2 | 3 | 2 | — | — | — |
+ | 4th | 2 | 4 | 3 | — | — | — |
+ | 5th | 2 | 4 | 3 | — | — | — |
+ | 6th | 2 | 4 | 3 | — | — | — |
+ | 7th | 2 | 5 | 4 | 2 | — | — |
+ | 8th | 2 | 6 | 4 | 2 | — | — |
+ | 9th | 2 | 6 | 4 | 2 | — | — |
+ | 10th | 3 | 7 | 4 | 3 | — | — |
+ | 11th | 3 | 8 | 4 | 3 | — | — |
+ | 12th | 3 | 8 | 4 | 3 | — | — |
+ | 13th | 3 | 9 | 4 | 3 | 2 | — |
+ | 14th | 3 | 10 | 4 | 3 | 2 | — |
+ | 15th | 3 | 10 | 4 | 3 | 2 | — |
+ | 16th | 3 | 11 | 4 | 3 | 3 | — |
+ | 17th | 3 | 11 | 4 | 3 | 3 | — |
+ | 18th | 3 | 11 | 4 | 3 | 3 | — |
+ | 19th | 3 | 12 | 4 | 3 | 3 | 1 |
+ | 20th | 3 | 13 | 4 | 3 | 3 | 1 |
+ }}\n\n`;
}
};
diff --git a/themes/V3/5ePHB/snippets/coverpage.gen.js b/themes/V3/5ePHB/snippets/coverpage.gen.js
index 0fb8ba7a4..865269f92 100644
--- a/themes/V3/5ePHB/snippets/coverpage.gen.js
+++ b/themes/V3/5ePHB/snippets/coverpage.gen.js
@@ -1,55 +1,46 @@
const _ = require('lodash');
+const dedent = require('dedent-tabs').default;
const titles = [
- 'The Burning Gallows',
- 'The Ring of Nenlast',
- 'Below the Blind Tavern',
- 'Below the Hungering River',
- 'Before Bahamut\'s Land',
- 'The Cruel Grave from Within',
- 'The Strength of Trade Road',
- 'Through The Raven Queen\'s Worlds',
- 'Within the Settlement',
- 'The Crown from Within',
- 'The Merchant Within the Battlefield',
- 'Ioun\'s Fading Traveler',
- 'The Legion Ingredient',
- 'The Explorer Lure',
- 'Before the Charming Badlands',
- 'The Living Dead Above the Fearful Cage',
- 'Vecna\'s Hidden Sage',
- 'Bahamut\'s Demonspawn',
- 'Across Gruumsh\'s Elemental Chaos',
- 'The Blade of Orcus',
- 'Beyond Revenge',
- 'Brain of Insanity',
- 'Breed Battle!, A New Beginning',
- 'Evil Lake, A New Beginning',
- 'Invasion of the Gigantic Cat, Part II',
- 'Kraken War 2020',
- 'The Body Whisperers',
- 'The Diabolical Tales of the Ape-Women',
- 'The Doctor Immortal',
- 'The Doctor from Heaven',
- 'The Graveyard',
- 'Azure Core',
- 'Core Battle',
- 'Core of Heaven: The Guardian of Amazement',
- 'Deadly Amazement III',
- 'Dry Chaos IX',
- 'Gate Thunder',
- 'Guardian: Skies of the Dark Wizard',
- 'Lute of Eternity',
- 'Mercury\'s Planet: Brave Evolution',
- 'Ruby of Atlantis: The Quake of Peace',
- 'Sky of Zelda: The Thunder of Force',
- 'Vyse\'s Skies',
- 'White Greatness III',
- 'Yellow Divinity',
- 'Zidane\'s Ghost'
+ 'The Burning Gallows', 'The Ring of Nenlast',
+ 'Below the Blind Tavern', 'Below the Hungering River',
+ 'Before Bahamut\'s Land', 'The Cruel Grave from Within',
+ 'The Strength of Trade Road', 'Through The Raven Queen\'s Worlds',
+ 'Within the Settlement', 'The Crown from Within',
+ 'The Merchant Within the Battlefield', 'Ioun\'s Fading Traveler',
+ 'The Legion Ingredient', 'The Explorer Lure',
+ 'Before the Charming Badlands', 'Vecna\'s Hidden Sage',
+ 'The Living Dead Above the Fearful Cage', 'Bahamut\'s Demonspawn',
+ 'Across Gruumsh\'s Elemental Chaos', 'The Blade of Orcus',
+ 'Beyond Revenge', 'Brain of Insanity',
+ 'A New Beginning', 'Evil Lake of the Merfolk',
+ 'Invasion of the Gigantic Cat, Part II', 'Kraken War 2020',
+ 'The Body Whisperers', 'The Doctor from Heaven',
+ 'The Diabolical Tales of the Ape-Women', 'The Doctor Immortal',
+ 'Core of Heaven: Guardian of Amazement', 'The Graveyard',
+ 'Guardian: Skies of the Dark Wizard', 'Lute of Eternity',
+ 'Mercury\'s Planet: Brave Evolution', 'Azure Core',
+ 'Sky of Zelda: The Thunder of Force', 'Core Battle',
+ 'Ruby of Atlantis: The Quake of Peace', 'Deadly Amazement III',
+ 'Dry Chaos IX', 'Gate Thunder',
+ 'Vyse\'s Skies', 'Blue Greatness III',
+ 'Yellow Divinity', 'Zidane\'s Ghost'
];
const subtitles = [
+ 'Tomb of Shadows', 'Dragon\'s Lair',
+ 'Lost Caverns', 'The Necromancer',
+ 'Mystic Forest', 'Cursed Ruins',
+ 'The Dark Abyss', 'Enchanted Maze',
+ 'Haunted Castle', 'Sands of Fate',
+ 'Dragon\'s Hoard', 'Undead Menace',
+ 'Lost City Ruins', 'Goblin Ambush',
+ 'Enchanted Forest', 'Darkness Rising',
+ 'Quest for Glory', 'Ancient Prophecy',
+ 'Shadowy Depths', 'Mystic Isles'
+];
+
+const footnote = [
'In an ominous universe, a botanist opposes terrorism.',
'In a demon-haunted city, in an age of lies and hate, a physicist tries to find an ancient treasure and battles a mob of aliens.',
'In a land of corruption, two cyberneticists and a dungeon delver search for freedom.',
@@ -74,51 +65,92 @@ const subtitles = [
'On a planet of mysticism, three travelers and a fire fighter quest for the ultimate weapon and oppose evil.',
'In a wicked universe, five seers fight lawlessness.',
'In a kingdom of death, in an era of illusion and blood, four colonists search for fame.',
- 'In an amazing kingdom, in an age of sorcery and lost souls, eight space pirates quest for freedom.',
- 'In a cursed empire, five inventors oppose terrorism.',
- 'On a crime-ridden planet of conspiracy, a watchman and an artificial intelligence try to find love and oppose lawlessness.',
- 'In a forgotten land, a reporter and a spy try to stop the apocalypse.',
- 'In a forbidden land of prophecy, a scientist and an archivist oppose a cabal of barbarians intent on stealing the souls of the innocent.',
- 'On an infernal world of illusion, a grave robber and a watchman try to find revenge and combat a syndicate of mages intent on stealing the source of all magic.',
- 'In a galaxy of dark magic, four fighters seek freedom.',
- 'In an empire of deception, six tomb-robbers quest for the ultimate weapon and combat an army of raiders.',
- 'In a kingdom of corruption and lost souls, in an age of panic, eight planetologists oppose evil.',
- 'In a galaxy of misery and hopelessness, in a time of agony and pain, five planetologists search for vengance.',
- 'In a universe of technology and insanity, in a time of sorcery, a computer techician quests for hope.',
- 'On a planet of dark magic and barbarism, in an age of horror and blasphemy, seven librarians search for fame.',
- 'In an empire of dark magic, in a time of blood and illusions, four monks try to find the ultimate weapon and combat terrorism.',
- 'In a forgotten empire of dark magic, six kings try to prevent the destruction of mankind.',
- 'In a galaxy of dark magic and horror, in an age of hopelessness, four marines and an outlaw combat evil.',
- 'In a mysterious city of illusion, in an age of computerization, a witch-hunter tries to find the ultimate weapon and opposes an evil corporation.',
- 'In a damned kingdom of technology, a virtual reality programmer and a fighter seek fame.',
- 'In a hellish kingdom, in an age of blasphemy and blasphemy, an astrologer searches for fame.',
- 'In a damned world of devils, an alien and a ranger quest for love and oppose a syndicate of demons.',
- 'In a cursed galaxy, in a time of pain, seven librarians hope to avert the apocalypse.',
- 'In a crime-infested galaxy, in an era of hopelessness and panic, three champions and a grave robber try to solve the ultimate crime.'
+ 'In an amazing kingdom, in an age of sorcery and lost souls, eight space pirates quest for freedom.'
+];
+
+const coverText = [
+ 'Embark on a thrilling journey across a vast and varied world, where magic and mystery await you at every turn. Encounter strange creatures and ancient secrets, and forge your own destiny with your choices. The world is yours to shape and explore.',
+ 'Join a band of brave adventurers and set out to explore the unknown lands beyond the horizon. Along the way, you’ll face perilous challenges, make new friends and enemies, and uncover a plot that threatens to destroy everything you hold dear. The fate of the world rests in your hands.',
+ 'Create your own character and enter a realm of endless possibilities, where you can be whoever you want to be. Whether you prefer to fight, sneak, charm, or craft your way through the game, you’ll find a style that suits you. The only limit is your imagination.',
+ 'Experience a rich and immersive story that adapts to your actions and decisions. Every choice you make has consequences, for good or ill. Will you be a hero or a villain? A leader or a follower? A friend or a foe? The choice is yours.',
+ 'Dive into a world of epic fantasy and adventure, where you can explore ancient civilizations, dark dungeons, and hidden secrets. Along the way, you’ll meet colorful characters, collect powerful items, and learn new skills. The more you play, the more you’ll discover.',
+ 'Explore a vast and dynamic world that changes according to your actions. You can shape the environment, influence the politics, and alter the history of the game world. But be careful, as every change has a ripple effect that may have unforeseen consequences.',
+ 'Enter a world of wonder and danger, where you can find allies and enemies among the various races and factions that inhabit it. You can choose to join or oppose any of them, or forge your own path. The game world is alive and responsive to your actions.'
];
+module.exports = {
+
+ front : function() {
+ return dedent`
+ {{frontCover}}
+
+ {{logo ![](/assets/naturalCritLogoRed.svg)}}
+
+ # ${_.sample(titles)}
+ ## ${_.sample(subtitles)}
+ ___
+
+ {{banner HOMEBREW}}
+
+ {{footnote
+ ${_.sample(footnote)}
+ }}
+
+ ![background image](https://i.imgur.com/IwHRrbF.jpg){position:absolute,bottom:0,left:0,height:100%}
+
+ \page`;
+ },
+
+ inside : function() {
+ return dedent`
+ {{insideCover}}
+
+ # ${_.sample(titles)}
+ ## ${_.sample(subtitles)}
+ ___
+
+ {{imageMaskCenter${_.random(1, 16)},--offsetX:0%,--offsetY:0%,--rotation:0
+ ![background image](https://i.imgur.com/IsfUnFR.jpg){position:absolute,bottom:0,left:0,height:100%}
+ }}
+
+ {{logo ![](/assets/naturalCritLogoRed.svg)}}
+
+ \page`;
+ },
+
+ part : function() {
+ return dedent`
+ {{partCover}}
+
+ # PART X
+ ## ${_.sample(subtitles)}
+
+ {{imageMaskEdge${_.random(1, 8)},--offset:10cm,--rotation:180
+ ![Background image](https://i.imgur.com/9TU96xY.jpg){position:absolute,bottom:0,left:0,height:100%}
+ }}
+
+ \page`;
+ },
+
+ back : function() {
+ return dedent`
+ {{backCover}}
+
+ # ${_.sample(subtitles)}
-module.exports = ()=>{
- return `
+ ${_.sampleSize(coverText, 3).join('\n:\n')}
+ ___
-{{margin-top:225px}}
+ For use with any fantasy roleplaying ruleset. Play the best game of your life!
-# ${_.sample(titles)}
+ ![background image](https://i.imgur.com/MJ4YHu7.jpg){position:absolute,bottom:0,left:0,height:100%}
-{{margin-top:25px}}
+ {{logo
+ ![](/assets/naturalCritLogoWhite.svg)
-{{wide
-##### ${_.sample(subtitles)}
-}}
+ Homebrewery.Naturalcrit.com
+ }}
-\\page`;
-};
\ No newline at end of file
+ \page`;
+ }
+};
diff --git a/themes/V3/5ePHB/snippets/index.gen.js b/themes/V3/5ePHB/snippets/index.gen.js
new file mode 100644
index 000000000..8de5df14c
--- /dev/null
+++ b/themes/V3/5ePHB/snippets/index.gen.js
@@ -0,0 +1,85 @@
+const dedent = require('dedent-tabs').default;
+
+module.exports = ()=>{
+ return dedent`
+ {{index,wide,columns:5;
+ ##### Index
+ - Ankhesh-Bort
+ - city map, 7
+ - city watch, 12
+ - guilds, 19
+ - Cheese
+ - types of cheese, 8
+ - cheese-related magic, 14
+ - cheese-related quests, 26-27
+ - Death
+ - appearance, 10
+ - personality, 13
+ - hobbies, 23
+ - Elves
+ - types of elves, 15
+ - elvish magic, 24
+ - elvish curses, 28
+ - Footnotes
+ - types of footnotes, 16-17
+ - footnote rules, 20-21
+ - footnote humor, 29-30
+ - Gods
+ - types of gods, 12
+ - godly interventions, 25
+ - godly conflicts, 31
+ - Heroes
+ - class features, 11-12
+ - heroic deeds, 26-27
+ - Inns
+ - types of inns, 9
+ - inn amenities, 18
+ - Jokes
+ - types of jokes, 11-12
+ - joke delivery, 25
+ - Knives
+ - types of knives, 16-17
+ - knife skills, 22-23
+ - knife fights, 28-29
+ - Luggage
+ - appearance, 10
+ - personality, 13
+ - abilities, 23
+ - Magic
+ - types of magic, 15
+ - magic rules, 24
+ - magic mishaps, 28
+ - Socks
+ - types of socks, 9
+ - sock-related magic (yes, really), 15
+ - sock-related quests (no, really), 26
+ - Trolls
+ - appearance and biology, 11
+ - culture and language, 18
+ - troll rights and activism, 31
+ - Unknown University
+ - history and architecture, 12
+ - faculty and staff, 20
+ - courses and exams, 33
+ - Vampires
+ - types and origins, 13
+ - vampiric powers and weaknesses, 21
+ - vampiric etiquette and politics, 34
+ - Witches
+ - types and traditions, 14
+ - witchcraft and headology, 22
+ - witch trials and tribulations, 35
+ - Xylophones
+ - musical instruments or weapons?, 15
+ - xylophone-related magic and lore, 23
+ - xylophone-related quests and puzzles, 36
+ - Yetis
+ - appearance and behavior, 16
+ - yeti philosophy and religion, 24
+ - yeti encounters and stories, 37
+ - Zombies
+ - types and causes, 17
+ - zombie rights and duties, 25
+ - zombie survival and prevention, 38
+ }}`;
+};
\ No newline at end of file
diff --git a/themes/V3/5ePHB/snippets/script.gen.js b/themes/V3/5ePHB/snippets/script.gen.js
new file mode 100644
index 000000000..61f56ec5f
--- /dev/null
+++ b/themes/V3/5ePHB/snippets/script.gen.js
@@ -0,0 +1,48 @@
+const _ = require('lodash');
+const dedent = require('dedent-tabs').default;
+
+module.exports = {
+ dwarvish : ()=>{
+ return dedent `##### Dwarvish Runes: Sample Alphabet
+ {{runeTable,wide,frame,font-family:Davek
+ | a | b | c | d | e | f | g | h | i | j | k | l | m |
+ |:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
+ | a | b | c | d | e | f | g | h | i | j | k | l | m |
+ :
+ | n | o | p | q | r | s | t | u | v | w | x | y | z |
+ |:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
+ | n | o | p | q | r | s | t | u | v | w | x | y | z |
+ }}\n\n`;
+ },
+ elvish : ()=>{
+ return dedent `##### Elvish Runes: Sample Alphabet
+ {{runeTable,wide,frame,font-family:Rellanic
+ | a | b | c | d | e | f | g | h | i | j | k | l | m |
+ |:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
+ | a | b | c | d | e | f | g | h | i | j | k | l | m |
+ :
+ | n | o | p | q | r | s | t | u | v | w | x | y | z |
+ |:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
+ | n | o | p | q | r | s | t | u | v | w | x | y | z |
+ }}\n\n`;
+ },
+ draconic : ()=>{
+ return dedent `##### Draconic Runes: Sample Alphabet
+ {{runeTable,wide,frame,font-family:Iokharic
+ | a | b | c | d | e | f | g | h | i | j | k | l | m |
+ |:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
+ | a | b | c | d | e | f | g | h | i | j | k | l | m |
+ :
+ | n | o | p | q | r | s | t | u | v | w | x | y | z |
+ |:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
+ | n | o | p | q | r | s | t | u | v | w | x | y | z |
+ }}\n\n`;
+ }
+
+
+};
+
+
+()=>{
+
+};
diff --git a/themes/V3/5ePHB/snippets/tableOfContents.gen.js b/themes/V3/5ePHB/snippets/tableOfContents.gen.js
index 1c52d5cf7..97d82ed40 100644
--- a/themes/V3/5ePHB/snippets/tableOfContents.gen.js
+++ b/themes/V3/5ePHB/snippets/tableOfContents.gen.js
@@ -29,27 +29,29 @@ const getTOC = (pages)=>{
const res = [];
_.each(pages, (page, pageNum)=>{
- const lines = page.split('\n');
- _.each(lines, (line)=>{
- if(_.startsWith(line, '# ')){
- const title = line.replace('# ', '');
- add1(title, pageNum);
- }
- if(_.startsWith(line, '## ')){
- const title = line.replace('## ', '');
- add2(title, pageNum);
- }
- if(_.startsWith(line, '### ')){
- const title = line.replace('### ', '');
- add3(title, pageNum);
- }
- });
+ if(!page.includes("{{frontCover}}") && !page.includes("{{insideCover}}") && !page.includes("{{partCover}}") && !page.includes("{{backCover}}")) {
+ const lines = page.split('\n');
+ _.each(lines, (line)=>{
+ if(_.startsWith(line, '# ')){
+ const title = line.replace('# ', '');
+ add1(title, pageNum);
+ }
+ if(_.startsWith(line, '## ')){
+ const title = line.replace('## ', '');
+ add2(title, pageNum);
+ }
+ if(_.startsWith(line, '### ')){
+ const title = line.replace('### ', '');
+ add3(title, pageNum);
+ }
+ });
+ }
});
return res;
};
-module.exports = function(brew){
- const pages = brew.text.split('\\page');
+module.exports = function(props){
+ const pages = props.brew.text.split('\\page');
const TOC = getTOC(pages);
const markdown = _.reduce(TOC, (r, g1, idx1)=>{
if(g1.title !== null) {
diff --git a/themes/V3/5ePHB/style.less b/themes/V3/5ePHB/style.less
index 85dc566f4..c6e87c40a 100644
--- a/themes/V3/5ePHB/style.less
+++ b/themes/V3/5ePHB/style.less
@@ -1,798 +1,1131 @@
-@layer V3_5ePHB {
- @import (less) './themes/fonts/5e/fonts.less';
- @import (less) './themes/assets/assets.less';
+@import (less) './themes/fonts/5e/fonts.less';
+@import (less) './themes/assets/assets.less';
- :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 : #F2E5B5; // Light orange parchment
- --HB_Color_CaptionText : #766649; // Brown
- --HB_Color_WatercolorStain : #BBAD82; // Light brown
- --HB_Color_Footnotes : #C9AD6A; // Gold
- }
+: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 : #F2E5B5; // 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;
+@page { margin: 0; }
+body {
+ counter-reset : phb-page-numbers;
+}
+*{
+ -webkit-print-color-adjust : exact;
+}
+.useSansSerif(){
+ font-family : ScalySansRemake;
+ font-size : 0.318cm;
+ line-height : 1.2em;
+ p,dl,ul,ol {
+ line-height : 1.2em;
}
- *{
- -webkit-print-color-adjust : exact;
+ ul, ol {
+ padding-left : 1em;
}
- .useSansSerif(){
- font-family : ScalySansRemake;
- font-size : 0.318cm;
- line-height : 1.2em;
- p,dl,ul,ol {
- line-height : 1.2em;
- }
- ul, ol {
- padding-left : 1em;
- }
- em{
- font-style : italic;
- }
- strong{
- font-weight : 800;
- letter-spacing : -0.02em;
- }
- h5 + * {
- margin-top : 0.1cm;
- }
- }
- .useColumns(@multiplier : 1, @fillMode: balance){
- column-count : 2;
- column-fill : @fillMode;
- column-gap : 0.9cm;
- column-width : 8cm * @multiplier;
- -webkit-column-count : 2;
- -moz-column-count : 2;
- -webkit-column-width : 8cm * @multiplier;
- -moz-column-width : 8cm * @multiplier;
- -webkit-column-gap : 0.9cm;
- -moz-column-gap : 0.9cm;
- }
- .columnWrapper{
- max-height : 100%;
- column-span : all;
- columns : inherit;
- column-gap : inherit;
- }
- .page{
- .useColumns();
- counter-increment : phb-page-numbers;
- position : relative;
- z-index : 15;
- box-sizing : border-box;
- overflow : hidden;
- height : 279.4mm;
- width : 215.9mm;
- background-color : var(--HB_Color_Background);
- background-image : @backgroundImage;
- padding : 1.4cm 1.9cm 1.7cm;
- font-family : BookInsanityRemake;
- font-size : 0.34cm;
- text-rendering : optimizeLegibility;
- page-break-before : always;
- page-break-after : always;
- }
- //*****************************
- // * BASE
- // *****************************/
+ em{
+ font-style : italic;
+ }
+ strong{
+ font-weight : 800;
+ letter-spacing : -0.02em;
+ }
+ h5 + * {
+ margin-top : 0.1cm;
+ }
+}
+.useColumns(@multiplier : 1, @fillMode: balance){
+ column-count : 2;
+ column-fill : @fillMode;
+ column-gap : 0.9cm;
+ column-width : 8cm * @multiplier;
+ -webkit-column-count : 2;
+ -moz-column-count : 2;
+ -webkit-column-width : 8cm * @multiplier;
+ -moz-column-width : 8cm * @multiplier;
+ -webkit-column-gap : 0.9cm;
+ -moz-column-gap : 0.9cm;
+}
+.columnWrapper{
+ max-height : 100%;
+ column-span : all;
+ columns : inherit;
+ column-gap : inherit;
+}
+.page{
+ .useColumns();
+ counter-increment : phb-page-numbers;
+ position : relative;
+ z-index : 15;
+ box-sizing : border-box;
+ overflow : hidden;
+ height : 279.4mm;
+ width : 215.9mm;
+ background-color : var(--HB_Color_Background);
+ background-image : @backgroundImage;
+ padding : 1.4cm 1.9cm 1.7cm;
+ font-family : BookInsanityRemake;
+ font-size : 0.34cm;
+ text-rendering : optimizeLegibility;
+ page-break-before : always;
+ page-break-after : always;
+}
+ //*****************************
+ // * BASE
+ // *****************************/
- .page{
- p{
- overflow-wrap : break-word; //TODO: MAKE ALL MARGINS TOP-ONLY. USE * + * STYLE SELECTORS
- display : block;
- line-height : 1.25em;
- &+* {
- margin-top : 0.325cm;
- }
- &+p{
- margin-top : 0;
- }
+.page{
+ p{
+ overflow-wrap : break-word; //TODO: MAKE ALL MARGINS TOP-ONLY. USE * + * STYLE SELECTORS
+ display : block;
+ line-height : 1.25em;
+ &+* {
+ margin-top : 0.325cm;
}
- ul{
- margin-bottom : 0.8em;
- padding-left : 1.4em;
- line-height : 1.25em;
- list-style-position : outside;
- list-style-type : disc;
- }
- ol{
- margin-bottom : 0.8em;
- padding-left : 1.4em;
- line-height : 1.25em;
- list-style-position : outside;
- list-style-type : decimal;
- }
- //Indents after p or lists
- p+p, ul+p, ol+p{
- text-indent : 1em;
- }
- img{
- z-index : -1;
- }
- strong{
- font-weight : bold;
- letter-spacing : -0.02em;
- }
- em{
- font-style : italic;
- }
- sup{
- vertical-align : super;
- font-size : smaller;
- line-height : 0;
- }
- sub{
- vertical-align : sub;
- font-size : smaller;
- line-height : 0;
- }
- //*****************************
- // * HEADERS
- // *****************************/
- h1,h2,h3,h4{
- font-family : MrEavesRemake;
- font-weight : 800;
- 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{
- float : left;
- font-family : SolberaImitationRemake;
- line-height : 1em;
- font-size : 3.5cm;
- padding-left : 40px; //Allow background color to extend into margins
- margin-left : -40px;
- margin-top : -0.3cm;
- padding-bottom : 2px;
- margin-bottom : -20px;
- background-image : linear-gradient(-45deg, #322814, #998250, #322814);
- background-clip : text;
- -webkit-background-clip : text;
- color : rgba(0, 0, 0, 0);
- }
- &+p::first-line{
- font-variant : small-caps;
- }
+ &+p{
+ margin-top : 0;
}
- h2{
- //margin-top : 0px; //Font is misaligned. Shift up slightly
- //margin-bottom : 0.05cm;
- font-size : 0.75cm;
- line-height : 0.988em; //Font is misaligned. Shift up slightly
+ }
+ ul{
+ margin-bottom : 0.8em;
+ padding-left : 1.4em;
+ line-height : 1.25em;
+ list-style-position : outside;
+ list-style-type : disc;
+ }
+ ol{
+ margin-bottom : 0.8em;
+ padding-left : 1.4em;
+ line-height : 1.25em;
+ list-style-position : outside;
+ list-style-type : decimal;
+ }
+ //Indents after p or lists
+ p+p, ul+p, ol+p{
+ text-indent : 1em;
+ }
+ img{
+ z-index : -1;
+ }
+ strong{
+ font-weight : bold;
+ letter-spacing : -0.02em;
+ }
+ em{
+ font-style : italic;
+ }
+ sup{
+ vertical-align : super;
+ font-size : smaller;
+ line-height : 0;
+ }
+ sub{
+ vertical-align : sub;
+ font-size : smaller;
+ line-height : 0;
+ }
+ //*****************************
+ // * HEADERS
+ // *****************************/
+ h1,h2,h3,h4{
+ font-family : MrEavesRemake;
+ font-weight : 800;
+ 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{
+ float : left;
+ font-family : SolberaImitationRemake;
+ line-height : 1em;
+ font-size : 3.5cm;
+ padding-left : 40px; //Allow background color to extend into margins
+ margin-left : -40px;
+ margin-top : -0.3cm;
+ padding-bottom : 2px;
+ margin-bottom : -20px;
+ background-image : linear-gradient(-45deg, #322814, #998250, #322814);
+ background-clip : text;
+ -webkit-background-clip : text;
+ color : rgba(0, 0, 0, 0);
}
- h3{
- //margin-top : -0.1cm; //Font is misaligned. Shift up slightly
- //margin-bottom : 0.1cm;
- font-size : 0.575cm;
- border-bottom : 2px solid var(--HB_Color_HeaderUnderline);;
- line-height : 0.995em; //Font is misaligned. Shift up slightly
- & + * {
- margin-top: 0.17cm;
- }
+ &+p::first-line{
+ font-variant : small-caps;
}
- * + h3 {
- margin-top : 0.155cm; //(0.325 - 0.17)
+ }
+ h2{
+ //margin-top : 0px; //Font is misaligned. Shift up slightly
+ //margin-bottom : 0.05cm;
+ font-size : 0.75cm;
+ line-height : 0.988em; //Font is misaligned. Shift up slightly
+ }
+ h3{
+ //margin-top : -0.1cm; //Font is misaligned. Shift up slightly
+ //margin-bottom : 0.1cm;
+ font-size : 0.575cm;
+ border-bottom : 2px solid var(--HB_Color_HeaderUnderline);;
+ line-height : 0.995em; //Font is misaligned. Shift up slightly
+ & + * {
+ margin-top: 0.17cm;
}
- h4{
- //margin-top : -0.02cm; //Font is misaligned. Shift up slightly
- //margin-bottom : 0.02cm;
- font-size : 0.458cm;
- line-height : 0.971em; //Font is misaligned. Shift up slightly
- & + * {
- margin-top: 0.09cm;
- }
+ }
+ * + h3 {
+ margin-top : 0.155cm; //(0.325 - 0.17)
+ }
+ h4{
+ //margin-top : -0.02cm; //Font is misaligned. Shift up slightly
+ //margin-bottom : 0.02cm;
+ font-size : 0.458cm;
+ line-height : 0.971em; //Font is misaligned. Shift up slightly
+ & + * {
+ margin-top: 0.09cm;
+ }
+ }
+ * + h4 {
+ margin-top : 0.235cm; //(0.325 - 0.09)
+ }
+ h5{
+ //margin-top : -0.02cm; //Font is misaligned. Shift up slightly
+ //margin-bottom : 0.02cm;
+ font-family : ScalySansSmallCapsRemake;
+ font-size : 0.423cm;
+ font-weight : 900;
+ line-height : 0.951em; //Font is misaligned. Shift up slightly
+ & + * {
+ margin-top : 0.2cm;
}
- * + h4 {
- margin-top : 0.235cm; //(0.325 - 0.09)
+ }
+ //*****************************
+ // * TABLE
+ // *****************************/
+ table{
+ .useSansSerif();
+ width : 100%;
+ line-height : 16px;
+ & + * {
+ margin-top : 0.325cm;
}
- h5{
- //margin-top : -0.02cm; //Font is misaligned. Shift up slightly
- //margin-bottom : 0.02cm;
- font-family : ScalySansSmallCapsRemake;
- font-size : 0.423cm;
- font-weight : 900;
- line-height : 0.951em; //Font is misaligned. Shift up slightly
- & + * {
- margin-top : 0.2cm;
+ thead{
+ display: table-row-group;
+ font-weight : 800;
+ th{
+ vertical-align : bottom;
+ //padding : 0.14em 0.4em;
+ padding : 0px 1.5px; // Both of these are temporary, just to force
+ //line-height : 16px; // PDF to render at same height until Chrome 108
}
}
- //*****************************
- // * TABLE
- // *****************************/
- table{
- .useSansSerif();
- width : 100%;
- line-height : 16px;
- & + * {
- margin-top : 0.325cm;
- }
- thead{
- display: table-row-group;
- font-weight : 800;
- th{
- vertical-align : bottom;
- //padding : 0.14em 0.4em;
+ tbody{
+ tr{
+ td{
+ //padding : 0.14em 0.4em;
padding : 0px 1.5px; // Both of these are temporary, just to force
- //line-height : 16px; // PDF to render at same height until Chrome 108
+ //line-height : 16px; // PDF to render at same height until Chrome 108
}
- }
- tbody{
- tr{
- td{
- //padding : 0.14em 0.4em;
- padding : 0px 1.5px; // Both of these are temporary, just to force
- //line-height : 16px; // PDF to render at same height until Chrome 108
- }
- &:nth-child(odd){
- background-color : var(--HB_Color_Accent);
- }
+ &:nth-child(odd){
+ background-color : var(--HB_Color_Accent);
}
}
}
- //*****************************
- // * NOTE
- // *****************************/
- .note{
- .useSansSerif();
- background-color : var(--HB_Color_Accent);
- border-style : solid;
- border-width : 1px;
- border-image : @noteBorderImage 12 stretch;
- border-image-outset : 9px 0px;
- border-image-width : 11px;
- padding : 0.13cm 0.16cm;
- filter : drop-shadow(1px 4px 6px #888);
- .page :where(&) {
- margin-top : 9px; //Prevent top border getting cut off on colbreak
- }
- & + * {
- margin-top : 0.45cm;
- }
- h5 {
- font-size : 0.375cm;
- }
- p{
- display : block;
- padding-bottom : 0px;
- }
- :last-child {
- margin-bottom : 0;
- }
+ }
+ //*****************************
+ // * NOTE
+ // *****************************/
+ .note{
+ .useSansSerif();
+ background-color : var(--HB_Color_Accent);
+ border-style : solid;
+ border-width : 1px;
+ border-image : @noteBorderImage 12 stretch;
+ border-image-outset : 9px 0px;
+ border-image-width : 11px;
+ padding : 0.13cm 0.16cm;
+ box-shadow : 1px 4px 14px #888;
+ .page :where(&) {
+ margin-top : 9px; //Prevent top border getting cut off on colbreak
}
- //************************************
- // * DESCRIPTIVE TEXT BOX
- // ************************************/
- .descriptive{
- .useSansSerif();
- background-color : #faf7ea;
- border-style : solid;
- border-width : 7px;
- border-image : @descriptiveBoxImage 12 stretch;
- border-image-outset : 4px;
- padding : 0.1em;
- filter : drop-shadow(0 0 3px #faf7ea);
- .page :where(&) {
- margin-top : 4px; //Prevent top border getting cut off on colbreak
- }
- & + * {
- margin-top : 0.45cm;
- }
- h5 {
- font-size : 0.375cm;
- }
- p{
- display : block;
- padding-bottom : 0px;
- line-height : 1.5em;
- }
- :last-child {
- margin-bottom : 0;
- }
+ & + * {
+ margin-top : 0.45cm;
+ }
+ h5 {
+ font-size : 0.375cm;
+ }
+ p{
+ display : block;
+ padding-bottom : 0px;
+ }
+ :last-child {
+ margin-bottom : 0;
+ }
+ }
+ //************************************
+ // * DESCRIPTIVE TEXT BOX
+ // ************************************/
+ .descriptive{
+ .useSansSerif();
+ background-color : #faf7ea;
+ border-style : solid;
+ border-width : 7px;
+ border-image : @descriptiveBoxImage 12 stretch;
+ border-image-outset : 4px;
+ padding : 0.1em;
+ box-shadow : 0 0 6px #faf7ea;
+ .page :where(&) {
+ margin-top : 4px; //Prevent top border getting cut off on colbreak
}
- //*****************************
- // * Images Snippets
- // *****************************/
+ & + * {
+ margin-top : 0.45cm;
+ }
+ h5 {
+ font-size : 0.375cm;
+ }
+ p{
+ display : block;
+ padding-bottom : 0px;
+ line-height : 1.5em;
+ }
+ :last-child {
+ margin-bottom : 0;
+ }
+ }
+ //*****************************
+ // * Images Snippets
+ // *****************************/
- /* Arist Credit */
- .artist {
- position : absolute;
- width : auto;
- text-align : center;
+ /* 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;
- 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;
- }
- }
}
-
- /* Watermark */
- .watermark {
- display : grid !important;
- place-items : center;
- justify-content : center;
- position : absolute;
- 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;
+ a{
+ color : inherit;
+ text-decoration : unset;
+ &:hover {
+ text-decoration : underline;
}
}
+ }
- /* 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;
+ /* Watermark */
+ .watermark {
+ display : grid !important;
+ place-items : center;
+ justify-content : center;
+ position : absolute;
+ 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;
}
+ }
- .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; }
+ /* 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;
+ }
- //*****************************
- // * MONSTER STAT BLOCK
- // *****************************/
- .monster {
- .useSansSerif();
- &.frame {
- border-style : solid;
- border-width : 7px 6px;
- background-color : var(--HB_Color_MonsterStatBackground);
- background-image : @monsterBlockBackground;
- border-image : @monsterBorderImage 14 round;
- border-image-outset : 0px 2px;
- background-blend-mode : overlay;
- background-attachment : fixed;
- filter : drop-shadow(1px 4px 6px #888);
- padding : 4px 2px;
- margin-left : -0.16cm;
- margin-right : -0.16cm;
- width : calc(100% + 0.32cm);
- }
+ .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; }
- position : relative;
- padding : 0px;
- margin-bottom : 0.325cm;
+ //*****************************
+ // * MONSTER STAT BLOCK
+ // *****************************/
+ .monster {
+ .useSansSerif();
+ &.frame {
+ border-style : solid;
+ border-width : 7px 6px;
+ background-color : var(--HB_Color_MonsterStatBackground);
+ background-image : @monsterBlockBackground;
+ border-image : @monsterBorderImage 14 round;
+ border-image-outset : 0px 2px;
+ background-blend-mode : overlay;
+ background-attachment : fixed;
+ box-shadow : 1px 4px 14px #888;
+ padding : 4px 2px;
+ margin-left : -0.16cm;
+ margin-right : -0.16cm;
+ width : calc(100% + 0.32cm);
+ }
- //Headers
- h2{
- font-size : 0.62cm;
- line-height : 1em;
- margin : 0;
- &+p {
- font-size : 0.304cm; //Monster size and type subtext
- margin-bottom : 0;
- }
- }
- h3{
- font-family : ScalySansRemake;
- font-weight : 800;
- font-variant : small-caps;
- border-bottom : 2px solid var(--HB_Color_HeaderText);
- // margin-top : 0.05cm; //Font is misaligned. Shift up slightly
- padding-bottom : 0.05cm;
- }
+ position : relative;
+ padding : 0px;
+ margin-bottom : 0.325cm;
- //Triangle dividers
- hr{
- visibility : visible;
- height : 6px;
- margin : 0.12cm 0cm;
- background-image : @redTriangleImage;
- background-size : 100% 100%;
- border : none;
+ //Headers
+ h2{
+ font-size : 0.62cm;
+ line-height : 1em;
+ margin : 0;
+ &+p {
+ font-size : 0.304cm; //Monster size and type subtext
+ margin-bottom : 0;
}
+ }
+ h3{
+ font-family : ScalySansRemake;
+ font-weight : 800;
+ font-variant : small-caps;
+ border-bottom : 2px solid var(--HB_Color_HeaderText);
+ // margin-top : 0.05cm; //Font is misaligned. Shift up slightly
+ padding-bottom : 0.05cm;
+ }
- //Attribute Lists - All text between HRs is red
- hr ~ :is(dl,p) {
- color : var(--HB_Color_HeaderText);
+ //Triangle dividers
+ hr{
+ visibility : visible;
+ height : 6px;
+ margin : 0.12cm 0cm;
+ background-image : @redTriangleImage;
+ background-size : 100% 100%;
+ border : none;
+ }
+
+ //Attribute Lists - All text between HRs is red
+ hr ~ :is(dl,p) {
+ color : var(--HB_Color_HeaderText);
+ }
+ hr:last-of-type {
+ & ~ :is(dl,p) {
+ color : inherit; // After the HRs, reset text to black
}
- hr:last-of-type {
- & ~ :is(dl,p) {
- color : inherit; // After the HRs, reset text to black
- }
- & + * {
- margin-top : 0.325cm; // Space after last HR
- }
+ & + * {
+ margin-top : 0.325cm; // Space after last HR
}
+ }
- // Monster Ability table
- hr + table:first-of-type{
- margin : 0;
- column-span : none;
- color : var(--HB_Color_HeaderText);
- background-color : transparent;
- border-style : none;
- border-image : none;
- -webkit-column-span : none;
- tr {
- background-color : transparent;
- }
- td,th {
- padding: 0px;
- }
+ // Monster Ability table
+ hr + table:first-of-type{
+ margin : 0;
+ column-span : none;
+ color : var(--HB_Color_HeaderText);
+ background-color : transparent;
+ border-style : none;
+ border-image : none;
+ -webkit-column-span : none;
+ tr {
+ background-color : transparent;
}
-
- :last-child {
- margin-bottom : 0;
+ td,th {
+ padding: 0px;
}
}
- //Full Width
- .monster.wide{
- .useColumns(0.96, @fillMode: balance);
+ :last-child {
+ margin-bottom : 0;
}
+ }
+
+ //Full Width
+ .monster.wide{
+ .useColumns(0.96, @fillMode: balance);
+ }
- //*****************************
- // * FOOTER
- // *****************************/
+ //*****************************
+ // * FOOTER
+ // *****************************/
+ &:after{
+ content : "";
+ position : absolute;
+ bottom : 0px;
+ left : 0px;
+ z-index : 100;
+ height : 50px;
+ width : 100%;
+ background-image : @footerAccentImage;
+ background-size : cover;
+ }
+ &:nth-child(even){
&:after{
- content : "";
- position : absolute;
- bottom : 0px;
- left : 0px;
- z-index : 100;
- height : 50px;
- width : 100%;
- background-image : @footerAccentImage;
- background-size : cover;
- }
- &:nth-child(even){
- &:after{
- transform : scaleX(-1);
- }
- .pageNumber{
- left : 2px;
- }
- .footnote{
- left : 80px;
- text-align : left;
- }
+ transform : scaleX(-1);
}
.pageNumber{
- position : absolute;
- right : 2px;
- bottom : 22px;
- width : 50px;
- font-size : 0.9em;
- color : var(--HB_Color_Footnotes);
- text-align : center;
- text-indent : 0;
- &.auto::after {
- content : counter(phb-page-numbers);
- }
+ left : 2px;
}
.footnote{
- position : absolute;
- right : 80px;
- bottom : 32px;
- z-index : 150;
- width : 200px;
- font-size : 0.8em;
- color : var(--HB_Color_Footnotes);
- text-align : right;
- }
- //************************************
- // * CODE BLOCKS
- // ************************************/
- code{
- font-family : "Courier New", Courier, monospace;
- font-size : 0.325;
- padding : 0px 4px;
- color : #58180d;
- background-color : #faf7ea;
- border-radius : 4px;
- white-space : pre-wrap;
- overflow-wrap : break-word;
+ left : 80px;
+ text-align : left;
}
-
- pre code{
- width : 100%;
- display : inline-block;
- 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;
- }
+ }
+ .pageNumber{
+ position : absolute;
+ right : 2px;
+ bottom : 22px;
+ width : 50px;
+ font-size : 0.9em;
+ color : var(--HB_Color_Footnotes);
+ text-align : center;
+ text-indent : 0;
+ &.auto::after {
+ content : counter(phb-page-numbers);
}
- //*****************************
- // * EXTRAS
- // *****************************/
- hr{
- visibility : hidden;
- margin : 0px;
+ }
+ .footnote{
+ position : absolute;
+ right : 80px;
+ bottom : 32px;
+ z-index : 150;
+ width : 200px;
+ font-size : 0.8em;
+ color : var(--HB_Color_Footnotes);
+ text-align : right;
+ }
+ //************************************
+ // * CODE BLOCKS
+ // ************************************/
+ code{
+ font-family : "Courier New", Courier, monospace;
+ font-size : 0.325;
+ padding : 0px 4px;
+ color : #58180d;
+ background-color : #faf7ea;
+ border-radius : 4px;
+ white-space : pre-wrap;
+ overflow-wrap : break-word;
+ }
+
+ pre code{
+ width : 100%;
+ display : inline-block;
+ 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
}
- .columnSplit {
- visibility : hidden;
- -webkit-column-break-after : always;
- break-after : always;
- -moz-column-break-after : always;
+ & + * {
+ margin-top : 0.325cm;
}
- //Avoid breaking up
- blockquote,table{
- z-index : 15;
- -webkit-column-break-inside : avoid;
- page-break-inside : avoid;
- break-inside : avoid;
+ }
+ //*****************************
+ // * EXTRAS
+ // *****************************/
+ hr{
+ visibility : hidden;
+ margin : 0px;
+ }
+ .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;
+ }
+ //Text indent right after table
+ table+p{
+ text-indent : 1em;
+ }
+ // 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;
+ }
+}
+//*****************************
+// * SPELL LIST
+// *****************************/
+.page .spellList{
+ .useSansSerif();
+ column-count : 2;
+ ul+h5{
+ margin-top : 15px;
+ }
+ p, ul{
+ font-size : 0.352cm;
+ line-height : 1.265em;
+ }
+ 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;
+}
+&.frame {
+ margin-top : 0.7cm;
+ margin-bottom : 0.9cm;
+ margin-left : -0.1cm;
+ margin-right : -0.1cm;
+ width : calc(100% + 0.2cm);
+ border-collapse : separate;
+ background-color : white;
+ border : initial;
+ border-style : solid;
+ border-image-outset : 0.4cm 0.3cm;
+ border-image-repeat : stretch;
+ border-image-slice : 200;
+ border-image-source : @frameBorderImage;
+ border-image-width : 47px;
+ &.wide:first-child {
+ margin-top: 0.12cm;
+ }
+ & + * {
+ margin-top: 0;
+ }
+}
+&.decoration {
+ position:relative;
+}
+&.decoration::before {
+ content :'';
+ position : absolute;
+ background-image : @classTableDecoration,
+ @classTableDecoration;
+ background-size : contain, contain;
+ background-repeat : no-repeat, no-repeat;
+ background-position : top, bottom;
+ width : 7.75cm;
+ height : calc(100% + 3.3cm);
+ top : 50%;
+ left : 50%;
+ transform : translateY(-50%) translateX(-50%);
+ filter : drop-shadow(0px 0px 1px #C8C5C080);
+ z-index : -1;
+}
+&.decoration.wide::before {
+ width : calc(100% + 3.3cm);
+ height : 7.75cm;
+ background-position : left, right;
+}
+h5 + table{
+ margin-top : 0.2cm;
+}
+}
+//*****************************
+// * FRONT COVER PAGE
+// *****************************/
+.page:has(.frontCover) {
+ columns : 1;
+ text-align : center;
+ &:after {
+ all: unset;
+ }
+ h1 {
+ text-shadow: unset;
+ filter : drop-shadow(0 0 1.5px black) drop-shadow(0 0 0 black)
+ drop-shadow(0 0 0 black) drop-shadow(0 0 0 black)
+ drop-shadow(0 0 0 black) drop-shadow(0 0 0 black)
+ drop-shadow(0 0 0 black) drop-shadow(0 0 0 black);
+ text-transform : uppercase;
+ font-weight : normal;
+ margin-top : 1.2cm;
+ margin-bottom : 0;
+ color : white;
+ font-family : NodestoCapsCondensed;
+ font-size : 2.245cm;
+ line-height : 0.85em;
+ }
+ h2 {
+ filter : drop-shadow(0 0 1px black) drop-shadow(0 0 0 black)
+ drop-shadow(0 0 0 black) drop-shadow(0 0 0 black)
+ drop-shadow(0 0 0 black) drop-shadow(0 0 0 black)
+ drop-shadow(0 0 0 black) drop-shadow(0 0 0 black);
+ font-family : NodestoCapsCondensed;
+ font-weight : normal;
+ font-size : 0.85cm;
+ letter-spacing : 0.1cm;
+ color : white;
+ }
+ hr {
+ display : block;
+ position : relative;
+ background-image : @horizontalRule;
+ background-size : 100% 100%;
+ visibility : visible;
+ height : 0.5cm;
+ width : 12cm;
+ border : none;
+ margin : auto;
+ filter : drop-shadow(0 0 3px black);
+ }
+ .banner {
+ filter : drop-shadow(2px 2px 2px black);
+ position : absolute;
+ left : 0;
+ bottom : 4.2cm;
+ background-image : url('/assets/coverPageBanner.svg');
+ height : 1.7cm;
+ width : 10.5cm;
+ color : white;
+ font-family : NodestoCapsCondensed;
+ font-weight : normal;
+ font-size : 1cm;
+ letter-spacing : 0.014cm;
+ text-align : left;
+ padding-left : 1cm;
+ display : flex;
+ justify-content : center;
+ flex-direction : column;
+ padding-top : 0.1cm;
+ }
+ .footnote {
+ filter : drop-shadow(0 0 0.7px black) drop-shadow(0 0 0 black)
+ drop-shadow(0 0 0 black) drop-shadow(0 0 0 black)
+ drop-shadow(0 0 0 black) drop-shadow(0 0 0 black)
+ drop-shadow(0 0 0 black) drop-shadow(0 0 0 black);
+ position : absolute;
+ text-align : center;
+ color : white;
+ font-size : 0.496cm;
+ bottom : 1.3cm;
+ left : 0;
+ right : 0;
+ margin-left : auto;
+ margin-right : auto;
+ width : 70%;
+ font-family : Overpass;
+ }
+ .logo {
+ position : absolute;
+ top : 0.5cm;
+ left : 0;
+ right : 0;
+ filter : drop-shadow(0 0 0.075cm black);
+ img {
+ height : 2cm;
+ width : 100%;
}
- //Text indent right after table
- table+p{
- text-indent : 1em;
+ }
+}
+//*****************************
+// * INSIDE COVER PAGE
+// *****************************/
+.page:has(.insideCover) {
+ columns : 1;
+ text-align : center;
+ &:after {
+ all : unset;
+ }
+ h1 {
+ font-family : NodestoCapsCondensed;
+ font-weight : normal;
+ font-size : 2.1cm;
+ margin-top : 1.2cm;
+ margin-bottom : 0;
+ text-transform : uppercase;
+ line-height : 0.85em;
+ }
+ h2 {
+ font-family : NodestoCapsCondensed;
+ font-weight : normal;
+ font-size : 0.85cm;
+ letter-spacing : 0.5cm;
+ }
+ hr {
+ display : block;
+ position : relative;
+ background-image : @horizontalRule;
+ background-size : 100% 100%;
+ visibility : visible;
+ height : 0.5cm;
+ width : 12cm;
+ border : none;
+ margin : auto;
+ }
+ .logo {
+ position : absolute;
+ bottom : 1cm;
+ left : 0;
+ right : 0;
+ height : 2cm;
+ img {
+ height : 2cm;
+ width : 100%;
}
- // Nested lists
- ul ul,ol ol,ul ol,ol ul{
- margin-bottom : 0px;
- margin-left : 1.5em;
+ }
+}
+//*****************************
+// * BACK COVER
+// *****************************/
+.page:has(.backCover) {
+ color: #fff;
+ columns: 1;
+ padding: 2.25cm 1.3cm 2cm 1.3cm;
+ &:after {
+ all: unset;
+ }
+ .columnWrapper {
+ width: 7.6cm;
+ }
+ .backCover {
+ position: absolute;
+ inset: 0;
+ width: 11cm;
+ background-image: @backCover;
+ background-repeat: no-repeat;
+ background-size: contain;
+ z-index: -1;
+ }
+ .blank {
+ height: 1.4em;
+ }
+ h1 {
+ margin-bottom: .3cm;
+ font-size: 1.35cm;
+ line-height: 0.95em;
+ font-family: NodestoCapsCondensed;
+ text-align: center;
+ color: #ED1C24;
+ }
+ h1+p::first-line,
+ h1+p::first-letter {
+ all: unset;
+ }
+ img {
+ position: absolute;
+ top: 0px;
+ height: 100%;
+ z-index: -2;
+ }
+ hr {
+ margin-left: auto;
+ margin-right: auto;
+ margin-top: 1.1cm;
+ height: .53cm;
+ width: 4.5cm;
+ visibility: visible;
+ background-image: @horizontalRule;
+ background-size: 100% 100%;
+ border: none;
+ }
+ p {
+ font-family: Overpass;
+ line-height: 1.5em;
+ font-size: 0.332cm;
+ }
+ hr+p {
+ text-align: center;
+ margin-top: .6cm;
+ }
+ .logo {
+ position: absolute;
+ z-index: 0;
+ height: 1.5cm;
+ left: 1.2cm;
+ bottom: 2cm;
+ width: 7.6cm;
+ img {
+ position: relative;
+ height : 1.5cm;
+ width : 100%;
+ z-index : 0;
}
- li{
- -webkit-column-break-inside : avoid;
- page-break-inside : avoid;
- break-inside : avoid;
+ p {
+ position: relative;
+ color: #fff;
+ font-family: NodestoCapsWide;
+ font-size: .4cm;
+ letter-spacing: 0.08em;
+ line-height: 1em;
+ text-align: center;
+ text-indent: 0;
+ width: 100%;
}
}
- //*****************************
- // * SPELL LIST
+}
+
+//*****************************
+ // * PART COVER
// *****************************/
- .page .spellList{
- .useSansSerif();
- column-count : 2;
- ul+h5{
- margin-top : 15px;
- }
- p, ul{
- font-size : 0.352cm;
- line-height : 1.265em;
+ .page:has(.partCover) {
+ columns : 1;
+ text-align : center;
+ padding-top: 0;
+
+ .partCover {
+ background-image: @partCoverHeaderPHB;
+ background-repeat: no-repeat;
+ position: absolute;
+ background-size: 100%;
+ top: 0;
+ left: 0;
+ height: 6cm;
+ width: 100%;
}
- 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;
+
+ h1 {
+ position: relative;
+ text-align: center;
+ text-transform: uppercase;
+ font-size: 2.3cm;
+ font-family: NodestoCapsCondensed;
+ margin-top: .4cm;
}
- &.wide{
- column-count : 4;
+
+ h2 {
+ font-family: Overpass;
+ font-size: 0.45cm;
+ position: relative;
+ margin-top: -0.7em;
+ line-height: 1.1em;
+ margin-left : auto;
+ margin-right : auto;
}
}
- //*****************************
- // * CLASS TABLE
- // *****************************/
- .page .classTable{
- th[colspan]:not([rowspan]) {
- white-space : nowrap;
+//*****************************
+// * TABLE OF CONTENTS
+// *****************************/
+.page {
+&:has(.toc):after {
+ display: none;
+}
+.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;
}
- &.frame {
- margin-top : 0.7cm;
- margin-bottom : 0.9cm;
- margin-left : -0.1cm;
- margin-right : -0.1cm;
- width : calc(100% + 0.2cm);
- border-collapse : separate;
- background-color : white;
- border : initial;
- border-style : solid;
- border-image-outset : 0.4cm 0.3cm;
- border-image-repeat : stretch;
- border-image-slice : 200;
- border-image-source : @frameBorderImage;
- border-image-width : 47px;
- &.wide:first-child {
- margin-top: 0.12cm;
+ }
+ h4 {
+ margin-top : 0.2cm;
+ line-height : 0.4cm;
+ & + ul li {
+ line-height: 1.2em;
+ }
+ }
+ ul{
+ padding-left : 0;
+ list-style-type : none;
+ margin-top : 0;
+ a {
+ width : 100%;
+ display : flex;
+ flex-flow : row nowrap;
+ justify-content : space-between;
+ }
+ li + li h3 {
+ margin-top : 0.26cm;
+ line-height : 1em
+ }
+ h3 span:first-child::after {
+ border : none;
+ }
+ span {
+ display : contents;
+ &:first-child::after {
+ content : "";
+ bottom : 0.08cm;
+ flex : 1;
+ margin-left : 0.08cm; /* Spacing before dot leaders */
+ margin-right : 0.16cm;
+ border-bottom : 0.05cm dotted #000;
+ margin-bottom : 0.08cm;
}
- & + * {
- margin-top: 0;
+ &:last-child {
+ display : inline-block;
+ align-self : flex-end;
+ font-family : "BookInsanityRemake";
+ font-size : 0.34cm;
+ font-weight : normal;
+ color : #000;
}
}
- &.decoration {
- position:relative;
- }
- &.decoration::before {
- content :'';
- position : absolute;
- background-image : @classTableDecoration,
- @classTableDecoration;
- background-size : contain, contain;
- background-repeat : no-repeat, no-repeat;
- background-position : top, bottom;
- width : 7.75cm;
- height : calc(100% + 3.3cm);
- top : 50%;
- left : 50%;
- transform : translateY(-50%) translateX(-50%);
- filter : drop-shadow(0px 0px 1px #C8C5C080);
- z-index : -1;
- }
- &.decoration.wide::before {
- width : calc(100% + 3.3cm);
- height : 7.75cm;
- background-position : left, right;
- }
- h5 + table{
- margin-top : 0.2cm;
+ ul { /*List indent*/
+ margin-left : 1em;
}
}
- //*****************************
- // * TABLE OF CONTENTS
- // *****************************/
- .page {
- &:has(.toc):after {
- display: none;
+ &.wide{
+ .useColumns(0.96, @fillMode: balance);
+ }
+}
+}
+
+//*****************************
+// * DEFINITION LISTS
+// *****************************/
+.page {
+ dl {
+ line-height : 1.25em;
+ padding-left : 1em;
+ white-space : pre-line;
+ & + * {
+ margin-top : 0.28cm;
}
- .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;
- }
+ }
+ dl + * {
+ margin-top : 0.17cm;
+ }
+ p + dl {
+ margin-top: 0.17cm;
+ }
+ dt {
+ display : inline;
+ margin-right : 5px;
+ margin-left : -1em;
+ }
+ dd {
+ display : inline;
+ margin-left : 0px;
+ text-indent : 0px;
+ }
+}
+
+//*****************************
+// * WIDE
+// *****************************/
+.page .wide{
+ margin-bottom : 0.325cm;
+}
+
+.page h1 + *{
+ margin-top : 0;
+}
+
+//*****************************
+// * RUNE TABLE
+// *****************************/
+.page {
+ .runeTable {
+ margin-block: 0.7cm;
+ table {
+ font-family : inherit;
+ tbody tr {
+ background: unset;
}
- h4 {
- margin-top : 0.2cm;
- line-height : 0.4cm;
- & + ul li {
- line-height: 1.2em;
- }
+ th, td {
+ width: 1.3cm;
+ height: 1.3cm;
+ vertical-align: middle;
+ text-transform: uppercase;
+ outline: 1px solid #000;
+ font-weight: normal;
}
- ul{
- padding-left : 0;
- list-style-type : none;
- margin-top : 0;
- a {
- width : 100%;
- display : flex;
- flex-flow : row nowrap;
- justify-content : space-between;
- }
- li + li h3 {
- margin-top : 0.26cm;
- line-height : 1em
- }
- h3 span:first-child::after {
- border : none;
- }
- span {
- display : contents;
- &:first-child::after {
- content : "";
- bottom : 0.08cm;
- flex : 1;
- margin-left : 0.08cm; /* Spacing before dot leaders */
- margin-right : 0.16cm;
- border-bottom : 0.05cm dotted #000;
- margin-bottom : 0.08cm;
- }
- &:last-child {
- display : inline-block;
- align-self : flex-end;
- font-family : "BookInsanityRemake";
- font-size : 0.34cm;
- font-weight : normal;
- color : #000;
- }
- }
- ul { /*List indent*/
- margin-left : 1em;
- }
+ th{
+ font-family: BookInsanityRemake;
+ font-size: 0.45cm;
}
- &.wide{
- .useColumns(0.96, @fillMode: balance);
+ td {
+ font-size: 0.7cm;
}
}
- }
- //*****************************
- // * DEFINITION LISTS
- // *****************************/
- .page {
- dl {
- line-height : 1.25em;
- padding-left : 1em;
- white-space : pre-line;
- & + * {
- margin-top : 0.28cm;
- }
- }
- dl + * {
- margin-top : 0.17cm;
- }
- p + dl {
- margin-top: 0.17cm;
+ &.frame {
+ border: initial;
+ border-style: solid;
+ border-image-outset: .45cm .35cm .4cm .4cm;
+ border-image-repeat: stretch;
+ border-image-slice: 170;
+ border-image-source: @scriptBorder;
+ border-image-width: 1.4cm;
}
- dt {
- display : inline;
- margin-right : 5px;
- margin-left : -1em;
- }
- dd {
- display : inline;
- margin-left : 0px;
- text-indent : 0px;
- }
}
+}
+//*****************************
+// * INDEX
+// *****************************/
+.page {
+ .index {
+ font-size : 0.218cm;
- //*****************************
- // * WIDE
- // *****************************/
- .page .wide{
- margin-bottom : 0.325cm;
- }
+ ul ul {
+ margin : 0;
+ }
+
+ ul {
+ padding-left : 0;
+ text-indent : 0;
+ list-style-type : none;
+ }
- .page h1 + *{
- margin-top : 0;
+ & > ul > li {
+ text-indent : -1.5em;
+ padding-left : 1.5em;
+ }
}
}
diff --git a/themes/V3/Blank/snippets.js b/themes/V3/Blank/snippets.js
index cd508cccb..72372c297 100644
--- a/themes/V3/Blank/snippets.js
+++ b/themes/V3/Blank/snippets.js
@@ -1,9 +1,9 @@
/* eslint-disable max-lines */
-const WatercolorGen = require('./snippets/watercolor.gen.js');
-const dedent = require('dedent-tabs').default;
-
-
+const WatercolorGen = require('./snippets/watercolor.gen.js');
+const ImageMaskGen = require('./snippets/imageMask.gen.js');
+const FooterGen = require('./snippets/footer.gen.js');
+const dedent = require('dedent-tabs').default;
module.exports = [
@@ -22,6 +22,53 @@ module.exports = [
icon : 'fas fa-file-alt',
gen : '\n\\page\n'
},
+ {
+ name : 'Page Number',
+ icon : 'fas fa-bookmark',
+ gen : '{{pageNumber 1}}\n'
+ },
+ {
+ name : 'Auto-incrementing Page Number',
+ icon : 'fas fa-sort-numeric-down',
+ gen : '{{pageNumber,auto}}\n'
+ },
+ {
+ name : 'Footer',
+ icon : 'fas fa-shoe-prints',
+ gen : FooterGen.createFooterFunc(),
+ subsnippets : [
+ {
+ name : 'Footer from H1',
+ icon : 'fas fa-dice-one',
+ gen : FooterGen.createFooterFunc(1)
+ },
+ {
+ name : 'Footer from H2',
+ icon : 'fas fa-dice-two',
+ gen : FooterGen.createFooterFunc(2)
+ },
+ {
+ name : 'Footer from H3',
+ icon : 'fas fa-dice-three',
+ gen : FooterGen.createFooterFunc(3)
+ },
+ {
+ name : 'Footer from H4',
+ icon : 'fas fa-dice-four',
+ gen : FooterGen.createFooterFunc(4)
+ },
+ {
+ name : 'Footer from H5',
+ icon : 'fas fa-dice-five',
+ gen : FooterGen.createFooterFunc(5)
+ },
+ {
+ name : 'Footer from H6',
+ icon : 'fas fa-dice-six',
+ gen : FooterGen.createFooterFunc(6)
+ }
+ ]
+ },
{
name : 'Vertical Spacing',
icon : 'fas fa-arrows-alt-v',
@@ -102,6 +149,68 @@ module.exports = [
icon : 'fas fa-fill-drip',
gen : WatercolorGen,
},
+ {
+ name : 'Watercolor Center',
+ icon : 'fac mask-center',
+ gen : ImageMaskGen.center,
+ experimental : true,
+ },
+ {
+ name : 'Watercolor Edge',
+ icon : 'fac mask-edge',
+ gen : ImageMaskGen.edge('bottom'),
+ experimental : true,
+ subsnippets : [
+ {
+ name : 'Top',
+ icon : 'fac position-top',
+ gen : ImageMaskGen.edge('top'),
+ },
+ {
+ name : 'Right',
+ icon : 'fac position-right',
+ gen : ImageMaskGen.edge('right'),
+ },
+ {
+ name : 'Bottom',
+ icon : 'fac position-bottom',
+ gen : ImageMaskGen.edge('bottom'),
+ },
+ {
+ name : 'Left',
+ icon : 'fac position-left',
+ gen : ImageMaskGen.edge('left'),
+ },
+ ]
+ },
+ {
+ name : 'Watercolor Corner',
+ icon : 'fac mask-corner',
+ gen : ImageMaskGen.corner,
+ experimental : true,
+ subsnippets : [
+ {
+ name : 'Top-Left',
+ icon : 'fac position-top-left',
+ gen : ImageMaskGen.corner('top', 'left'),
+ },
+ {
+ name : 'Top-Right',
+ icon : 'fac position-top-right',
+ gen : ImageMaskGen.corner('top', 'right'),
+ },
+ {
+ name : 'Bottom-Left',
+ icon : 'fac position-bottom-left',
+ gen : ImageMaskGen.corner('bottom', 'left'),
+ },
+ {
+ name : 'Bottom-Right',
+ icon : 'fac position-bottom-right',
+ gen : ImageMaskGen.corner('bottom', 'right'),
+ }
+ ]
+ },
{
name : 'Watermark',
icon : 'fas fa-id-card',
diff --git a/themes/V3/Blank/snippets/footer.gen.js b/themes/V3/Blank/snippets/footer.gen.js
new file mode 100644
index 000000000..6583cd06e
--- /dev/null
+++ b/themes/V3/Blank/snippets/footer.gen.js
@@ -0,0 +1,17 @@
+const Markdown = require('../../../../shared/naturalcrit/markdown.js');
+
+module.exports = {
+ createFooterFunc : function(headerSize=1){
+ return (props)=>{
+ const cursorPos = props.cursorPos;
+
+ const markdownText = props.brew.text.split('\n').slice(0, cursorPos.line).join('\n');
+ const markdownTokens = Markdown.marked.lexer(markdownText);
+ const headerToken = markdownTokens.findLast((lexerToken)=>{ return lexerToken.type === 'heading' && lexerToken.depth === headerSize; });
+ const headerText = headerToken?.tokens.map((token)=>{ return token.text; }).join('');
+ const outputText = headerText || 'PART 1 | SECTION NAME';
+
+ return `\n{{footnote ${outputText}}}\n`;
+ };
+ }
+};
\ No newline at end of file
diff --git a/themes/V3/Blank/snippets/imageMask.gen.js b/themes/V3/Blank/snippets/imageMask.gen.js
new file mode 100644
index 000000000..323f89a1f
--- /dev/null
+++ b/themes/V3/Blank/snippets/imageMask.gen.js
@@ -0,0 +1,46 @@
+const _ = require('lodash');
+const dedent = require('dedent-tabs').default;
+
+module.exports = {
+ center : ()=>{
+ return dedent`
+ {{imageMaskCenter${_.random(1, 16)},--offsetX:0%,--offsetY:0%,--rotation:0
+ ![](https://i.imgur.com/GZfjDWV.png){height:100%}
+ }}
+ \n\n`;
+ },
+
+ edge : (side = 'bottom')=>{
+ const rotation = {
+ 'bottom' : 0,
+ 'top' : 180,
+ 'left' : 90,
+ 'right' : 270
+ }[side];
+ return dedent`
+ {{imageMaskEdge${_.random(1, 8)},--offset:0%,--rotation:${rotation}
+ ![](https://i.imgur.com/GZfjDWV.png){height:100%}
+ }}
+ \n\n`;
+ },
+
+ corner : (y = 'top', x = 'left')=>{
+ const offsetX = (x == 'left' ? '-50%' : '50%');
+ const offsetY = (y == 'top' ? '50%' : '-50%');
+ return dedent`
+ {{imageMaskCorner${_.random(1, 37)},--offsetX:${offsetX},--offsetY:${offsetY},--rotation:0
+ ![](https://i.imgur.com/GZfjDWV.png){height:100%}
+ }}
+ \n\n`;
+ }
+
+};
+
+()=>{
+
+};
diff --git a/themes/V3/Blank/style.less b/themes/V3/Blank/style.less
index 387b6612f..38aa42f20 100644
--- a/themes/V3/Blank/style.less
+++ b/themes/V3/Blank/style.less
@@ -1,278 +1,464 @@
-@layer V3_Blank {
- @import (less) './themes/fonts/5e/fonts.less';
- @import (less) './themes/assets/assets.less';
+@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
+: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;
+}
+
+//*****************************
+// * MUSTACHE DIVS/SPANS
+// *****************************/
+.page {
+ .block {
+ break-inside : avoid;
+ display : inline-block;
+ width : 100%;
+ img {
+ z-index : 0;
+ }
}
+ .inline-block {
+ display : inline-block;
+ text-indent : initial;
+ }
+}
- @page { margin: 0; }
- body {
- counter-reset : phb-page-numbers;
+.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;
+ contain : size;
+}
+ //*****************************
+ // * BASE
+ // *****************************/
+.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;
}
- *{
- -webkit-print-color-adjust : exact;
+ 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;
}
- .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;
- contain : size;
- }
- //*****************************
- // * BASE
- // *****************************/
- .page{
- p{
- overflow-wrap : break-word;
- display : block;
- }
- strong{
+ //*****************************
+ // * 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;
}
- 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;
- }
+ }
+ div:not(.columnWrapper) > table + table { // Side-by-side tables should not
+ margin-top : 0; // have vertical spacing.
+ }
- //*****************************
- // * HEADERS
- // *****************************/
- h1,h2,h3,h4,h5,h6{
- font-weight : bold;
- line-height : 1.2em;
+ //************************************
+ // * 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;
+ margin-top : 0;
+ & + * {
+ margin-top : 0;
}
- h1{
- font-size : 2em;
+ }
+ //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;
+ }
+
+ /* 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;
+ mix-blend-mode : overlay;
+ opacity : 30%;
+ transform : rotate(-45deg);
+ z-index : 500;
+ p {
+ margin-bottom : none;
}
- h2{
- font-size : 1.5em;
+ }
+
+ /* 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; }
+
+ /* Image Masks */
+
+ [class*="imageMask"] {
+ position : absolute;
+ height : 200%;
+ width : 200%;
+ left : 50%;
+ bottom : 50%;
+ --rotation : 0;
+ --revealer : none;
+ --checkerboard : none;
+ --scaleX : 1;
+ --scaleY : 1;
+ -webkit-mask-image : var(--wc), var(--revealer);
+ -webkit-mask-repeat : repeat-x;
+ -webkit-mask-size : 50%; //Scale only X to fit page width, leave height at aspect ratio, designed to hang off the edge
+ -webkit-mask-position : 50% calc(50% - var(--offset));
+ mask-image : var(--wc);
+ mask-repeat : repeat-x;
+ mask-size : 50%;
+ mask-position : 50% calc(50% - var(--offset));
+ background-image : var(--checkerboard);
+ background-size : 20px;
+ z-index : -1;
+ transform : translateY(50%) translateX(-50%) rotate(calc(1deg * var(--rotation))) scaleX(var(--scaleX)) scaleY(var(--scaleY));
+ & > p:has(img) {
+ position : absolute;
+ width : 50%;
+ height : 50%;
+ bottom : 50%;
+ left : 50%;
+ transform : translateX(-50%) translateY(50%) rotate(calc(-1deg * var(--rotation))) scaleX(calc(1 / var(--scaleX))) scaleY(calc(1 / var(--scaleY)));
}
- h3{
- font-size : 1.17em;
+ & img {
+ position : absolute;
+ display : block;
+ bottom : 0;
}
- h4{
- font-size : 1em;
+ &.bottom {
+ --rotation : 0;
+ & img {bottom: 0;}
}
- h5{
- font-size : 0.83em;
+ &.top {
+ --rotation : 180;
+ & img {top: 0;}
}
- //*****************************
- // * TABLE
- // *****************************/
- table{
- width : 100%;
- thead{
- display : table-row-group;
- font-weight : bold;
- }
+ &.left {
+ --rotation : 90;
+ & img {left: 0;}
}
- div:not(.columnWrapper) > table + table { // Side-by-side tables should not
- margin-top : 0; // have vertical spacing.
+ &.right {
+ --rotation : -90;
+ & img {right: 0;}
}
-
- /* 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;
- }
+ &.revealImage {
+ --revealer : linear-gradient(0deg, rgba(0,0,0,.2) 0%, rgba(0,0,0,0.2));
+ --checkerboard : url(/assets/waterColorMasks/missingImage.png); //shows any masked regions not filled by image
}
+ }
- /* 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;
- }
+ .imageMaskEdge {
+ &1 { --wc : url(/assets/waterColorMasks/edge/0001.webp); }
+ &2 { --wc : url(/assets/waterColorMasks/edge/0002.webp); }
+ &3 { --wc : url(/assets/waterColorMasks/edge/0003.webp); }
+ &4 { --wc : url(/assets/waterColorMasks/edge/0004.webp); }
+ &5 { --wc : url(/assets/waterColorMasks/edge/0005.webp); }
+ &6 { --wc : url(/assets/waterColorMasks/edge/0006.webp); }
+ &7 { --wc : url(/assets/waterColorMasks/edge/0007.webp); }
+ &8 { --wc : url(/assets/waterColorMasks/edge/0008.webp); }
+ }
- .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; }
+ [class*="imageMaskCenter"] {
+ width : 100%;
+ height : 100%;
+ left : calc(var(--offsetX));
+ bottom : calc(var(--offsetY));
+ -webkit-mask-image : var(--wc), var(--revealer);
+ -webkit-mask-repeat : no-repeat;
+ -webkit-mask-size : 100% 100%; //Scale both dimensions to fit page size
+ -webkit-mask-position : 0% 0%;
+ mask-image : var(--wc), var(--revealer);
+ mask-repeat : no-repeat;
+ mask-size : 100% 100%; //Scale both dimensions to fit page size
+ mask-position : 50% 50%;
+ transform : rotate(calc(1deg * var(--rotation))) scaleX(var(--scaleX)) scaleY(var(--scaleY));
- //************************************
- // * CODE BLOCKS
- // ************************************/
- code{
- font-family : "Courier New", Courier, monospace;
- white-space : pre-wrap;
- overflow-wrap : break-word;
+ & > p:has(img) {
+ position : absolute;
+ width : 100%;
+ height : 100%;
+ bottom : 0;
+ left : 0;
+ transform : unset;
+ transform : scaleX(calc(1 / var(--scaleX))) scaleY(calc(1 / var(--scaleY)))
+ rotate(calc(-1deg * var(--rotation)))
+ translateX(calc(-1 * var(--offsetX)))
+ translateY(calc(1 * var(--offsetY)));
}
+ }
- pre code{
- width : 100%;
- display : inline-block;
- }
- //*****************************
- // * EXTRAS
- // *****************************/
- .columnSplit {
- visibility : hidden;
- -webkit-column-break-after : always;
- break-after : always;
- -moz-column-break-after : always;
- margin-top : 0;
- & + * {
- margin-top : 0;
- }
- }
- //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;
- }
+ .imageMaskCenter {
+ &1 { --wc : url(/assets/waterColorMasks/center/0001.webp); }
+ &2 { --wc : url(/assets/waterColorMasks/center/0002.webp); }
+ &3 { --wc : url(/assets/waterColorMasks/center/0003.webp); }
+ &4 { --wc : url(/assets/waterColorMasks/center/0004.webp); }
+ &5 { --wc : url(/assets/waterColorMasks/center/0005.webp); }
+ &6 { --wc : url(/assets/waterColorMasks/center/0006.webp); }
+ &7 { --wc : url(/assets/waterColorMasks/center/0007.webp); }
+ &8 { --wc : url(/assets/waterColorMasks/center/0008.webp); }
+ &9 { --wc : url(/assets/waterColorMasks/center/0009.webp); }
+ &10 { --wc : url(/assets/waterColorMasks/center/0010.webp); }
+ &11 { --wc : url(/assets/waterColorMasks/center/0011.webp); }
+ &12 { --wc : url(/assets/waterColorMasks/center/0012.webp); }
+ &13 { --wc : url(/assets/waterColorMasks/center/0013.webp); }
+ &14 { --wc : url(/assets/waterColorMasks/center/0014.webp); }
+ &15 { --wc : url(/assets/waterColorMasks/center/0015.webp); }
+ &16 { --wc : url(/assets/waterColorMasks/center/0016.webp); }
+ &special { --wc : url(/assets/waterColorMasks/center/special.webp); }
}
- //*****************************
- // * MUSTACHE DIVS/SPANS
- // *****************************/
- .page {
- .block {
- break-inside : avoid;
- display : inline-block;
- width : 100%;
- }
- .inline-block {
- display : inline-block;
- text-indent : initial;
+
+ [class*="imageMaskCorner"] {
+ height : 200%;
+ width : 200%;
+ left : calc(-50% + var(--offsetX));
+ bottom : calc(-50% + var(--offsetY));
+ -webkit-mask-image : var(--wc), var(--revealer);
+ -webkit-mask-repeat : no-repeat;
+ -webkit-mask-size : 100% 100%; //Scale both dimensions to fit page size
+ -webkit-mask-position : 50% 50%;
+ mask-image : var(--wc), var(--revealer);
+ mask-repeat : no-repeat;
+ mask-size : 100% 100%; //Scale both dimensions to fit page size
+ mask-position : 50% 50%;
+ transform : rotate(calc(1deg * var(--rotation))) scaleX(var(--scaleX)) scaleY(var(--scaleY));
+ & > p:has(img) {
+ width : 50%;
+ height : 50%; //Complex transform below to handle mix of % and cm offsets
+ left : 25%;
+ bottom : 25%;
+ transform : scaleX(calc(1 / var(--scaleX))) scaleY(calc(1 / var(--scaleY)))
+ rotate(calc(-1deg * var(--rotation)))
+ translateX(calc(-1 * var(--offsetX)))
+ translateY(calc(1 * var(--offsetY)));
}
}
+ .imageMaskCorner {
+ &1 { --wc : url(/assets/waterColorMasks/corner/0001.webp); }
+ &2 { --wc : url(/assets/waterColorMasks/corner/0002.webp); }
+ &3 { --wc : url(/assets/waterColorMasks/corner/0003.webp); }
+ &4 { --wc : url(/assets/waterColorMasks/corner/0004.webp); }
+ &5 { --wc : url(/assets/waterColorMasks/corner/0005.webp); }
+ &6 { --wc : url(/assets/waterColorMasks/corner/0006.webp); }
+ &7 { --wc : url(/assets/waterColorMasks/corner/0007.webp); }
+ &8 { --wc : url(/assets/waterColorMasks/corner/0008.webp); }
+ &9 { --wc : url(/assets/waterColorMasks/corner/0009.webp); }
+ &10 { --wc : url(/assets/waterColorMasks/corner/0010.webp); }
+ &11 { --wc : url(/assets/waterColorMasks/corner/0011.webp); }
+ &12 { --wc : url(/assets/waterColorMasks/corner/0012.webp); }
+ &13 { --wc : url(/assets/waterColorMasks/corner/0013.webp); }
+ &14 { --wc : url(/assets/waterColorMasks/corner/0014.webp); }
+ &15 { --wc : url(/assets/waterColorMasks/corner/0015.webp); }
+ &16 { --wc : url(/assets/waterColorMasks/corner/0016.webp); }
+ &17 { --wc : url(/assets/waterColorMasks/corner/0017.webp); }
+ &18 { --wc : url(/assets/waterColorMasks/corner/0018.webp); }
+ &19 { --wc : url(/assets/waterColorMasks/corner/0019.webp); }
+ &20 { --wc : url(/assets/waterColorMasks/corner/0020.webp); }
+ &21 { --wc : url(/assets/waterColorMasks/corner/0021.webp); }
+ &22 { --wc : url(/assets/waterColorMasks/corner/0022.webp); }
+ &23 { --wc : url(/assets/waterColorMasks/corner/0023.webp); }
+ &24 { --wc : url(/assets/waterColorMasks/corner/0024.webp); }
+ &25 { --wc : url(/assets/waterColorMasks/corner/0025.webp); }
+ &26 { --wc : url(/assets/waterColorMasks/corner/0026.webp); }
+ &27 { --wc : url(/assets/waterColorMasks/corner/0027.webp); }
+ &28 { --wc : url(/assets/waterColorMasks/corner/0028.webp); }
+ &29 { --wc : url(/assets/waterColorMasks/corner/0029.webp); }
+ &30 { --wc : url(/assets/waterColorMasks/corner/0030.webp); }
+ &31 { --wc : url(/assets/waterColorMasks/corner/0031.webp); }
+ &32 { --wc : url(/assets/waterColorMasks/corner/0032.webp); }
+ &33 { --wc : url(/assets/waterColorMasks/corner/0033.webp); }
+ &34 { --wc : url(/assets/waterColorMasks/corner/0034.webp); }
+ &35 { --wc : url(/assets/waterColorMasks/corner/0035.webp); }
+ &36 { --wc : url(/assets/waterColorMasks/corner/0036.webp); }
+ &37 { --wc : url(/assets/waterColorMasks/corner/0037.webp); }
+ }
+}
- //*****************************
- // * DEFINITION LISTS
- // *****************************/
- .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;
- }
+//*****************************
+// * DEFINITION LISTS
+// *****************************/
+.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
- // *****************************/
- .page {
- .blank {
- height : 1em;
+//*****************************
+// * BLANK LINE
+// *****************************/
+.page {
+ .blank {
+ height : 1em;
+ margin-top : 0;
+ & + * {
margin-top : 0;
- & + * {
- margin-top : 0;
- }
}
}
+}
- //*****************************
- // * WIDE
- // *****************************/
- .page {
- .wide{
- column-span : all;
- display : block;
- margin-bottom : 1em;
- &+* {
- margin-top : 0;
- }
+//*****************************
+// * WIDE
+// *****************************/
+.page {
+ .wide{
+ column-span : all;
+ display : block;
+ margin-bottom : 1em;
+ &+* {
+ margin-top : 0;
}
}
}
diff --git a/themes/V3/Journal/style.less b/themes/V3/Journal/style.less
index f3b70cec2..2e2ada5c8 100644
--- a/themes/V3/Journal/style.less
+++ b/themes/V3/Journal/style.less
@@ -1,561 +1,559 @@
-@layer V3_Journal {
- @import (less) './themes/fonts/Journal/fonts.less';
- @import (less) './themes/assets/assets.less';
+@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
- }
+: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;
+.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;
- 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;
+ 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
}
- .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;
+ & .columnWrapper {
+ //transform: rotate(-0.5deg); // Breaks absolute positioning of images/footers. Wait for Chrome fix
+ }
+}
+
+ //*****************************
+ // * BASE
+ // *****************************/
+.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) {
- background-position : right;
- padding : 2.1cm 3.9cm 1.7cm 1.8cm;
+ transform:rotate(1deg);
}
- &:nth-of-type(2) {
- background-image : url(/assets/Journal/Background2.webp); //Only first page should show ribbon
+ &:nth-of-type(3n) {
+ transform:rotate(-1.5deg);
}
-
- & .columnWrapper {
- //transform: rotate(-0.5deg); // Breaks absolute positioning of images/footers. Wait for Chrome fix
+ }
+ 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;
}
}
-
- //*****************************
- // * BASE
- // *****************************/
- .page{
- color : var(--HB_Color_Text);
- font-family : ReenieBeanie;
- font-size : 0.53cm;
- line-height : 0.8em;
- p + * {
+ //*****************************
+ // * TABLE
+ // *****************************/
+ table{
+ .useSansSerif();
+ & + * {
margin-top : 0.325cm;
}
- p + p{
- margin-top : 0;
+ thead{
+ th{
+ vertical-align : bottom;
+ padding : 0.14em 0;
+ }
}
- ul{
- margin-bottom : 0.8em;
+ tbody{
+ tr{
+ td{
+ padding : 0.14em 0;
+ }
+ &:nth-child(odd){
+ background-image : linear-gradient(to left, #41212100, #41212122, #41212100);
+ }
+ }
}
- ol{
- margin-bottom : 0.8em;
+ }
+ //*****************************
+ // * 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
}
- em{
- text-decoration : underline;
- font-style : unset;
+ & + * {
+ margin-top : 0.45cm;
}
- del{
- text-decoration-style: double;
+ h5 {
+ font-size : 0.375cm;
}
-
- //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;
- }
+ p{
+ padding-bottom : 0px;
}
- h2{
- font-size : 0.62cm;
- line-height : 0.988em; //Font is misaligned. Shift up slightly
+ :last-child {
+ margin-bottom : 0;
}
- 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);
- }
+ }
+ //************************************
+ // * 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
}
- 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;
- }
+ & + * {
+ margin-top : 0.45cm;
}
- //*****************************
- // * 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);
- }
- }
- }
+ h5 {
+ font-size : 0.375cm;
}
- //*****************************
- // * 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;
- }
+ p{
+ padding-bottom : 0px;
}
- //************************************
- // * 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;
- }
+ :last-child {
+ margin-bottom : 0;
}
- //*****************************
- // * Images Snippets
- // *****************************/
+ }
+ //*****************************
+ // * Images Snippets
+ // *****************************/
- /* Arist Credit */
- .artist {
- position : absolute;
- width : auto;
- text-align : center;
+ /* 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;
- 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;
+ a{
+ color : inherit;
+ text-decoration : unset;
+ &:hover {
+ text-decoration : underline;
}
}
+ }
- //Full Width
- .monster.wide{
- .useColumns(0.96, @fillMode: balance);
+ //*****************************
+ // * 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;
}
- //*****************************
- // * FOOTER
- // *****************************/
- &:nth-child(odd){
- .pageNumber{
- left : 3cm;
- }
- .footnote{
- left : 4.5cm;
- text-align : left;
+ 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
}
}
- .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);
- }
+ h3{
+ margin-left : 0;
+ font-variant : small-caps;
+ padding-bottom : 0.05cm;
}
- .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;
+ 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
}
- 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
+ // 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;
}
- & + * {
- margin-top : 0.325cm;
+ td,th {
+ padding: 0px;
}
}
- //*****************************
- // * 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;
+
+ :last-child {
+ margin-bottom : 0;
}
- a:hover {
- color:red;
+
+ strong, em {
+ font-style : normal;
+ text-decoration : none;
}
}
+
+ //Full Width
+ .monster.wide{
+ .useColumns(0.96, @fillMode: balance);
+ }
+
//*****************************
- // * SPELL LIST
+ // * FOOTER
// *****************************/
-
- .page .spellList{
- .useSansSerif();
- font-family : PermanentMarker;
- column-count : 2;
- ul+h5{
- margin-top : 15px;
+ &:nth-child(odd){
+ .pageNumber{
+ left : 3cm;
}
- 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;
+ .footnote{
+ left : 4.5cm;
+ text-align : left;
}
- &.wide{
- column-count : 4;
+ }
+ .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;
+ }
- //*****************************
- // * CLASS TABLE
- // *****************************/
- .page .classTable{
- th[colspan]:not([rowspan]) {
- white-space : nowrap;
- }
- h5 + table{
- margin-top : 0.2cm;
+ 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;
}
}
//*****************************
- // * TABLE OF CONTENTS
+ // * EXTRAS
// *****************************/
- .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;
- }
+ 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;
- }
+ }
+ 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{
+ 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;
}
}
- ul { /*List indent*/
- margin-left : 1em;
+ &: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 */
}
}
- &.wide{
- .useColumns(0.96, @fillMode: balance);
+ ul { /*List indent*/
+ margin-left : 1em;
}
}
-
- //*****************************
- // * WIDE
- // *****************************/
- .page .wide {
- margin-bottom : 0.45cm;
+ &.wide{
+ .useColumns(0.96, @fillMode: balance);
}
}
+
+//*****************************
+// * WIDE
+// *****************************/
+.page .wide {
+ margin-bottom : 0.45cm;
+}
diff --git a/themes/assets/assets.less b/themes/assets/assets.less
index 7df5db0f6..cdef32c7c 100644
--- a/themes/assets/assets.less
+++ b/themes/assets/assets.less
@@ -10,6 +10,14 @@
@monsterBorderImage : url('/assets/monsterBorderFancy.png');
@codeBorderImage : url('/assets/codeBorder.png');
@classTableDecoration : url('/assets/classTableDecoration.png');
+@naturalCritLogo : url('/assets/naturalCritLogo.svg');
+@coverPageBanner : url('/assets/coverPageBanner.svg');
+@horizontalRule : url('/assets/horizontalRule.svg');
+@partCoverHeaderPHB : url('/assets/partCoverHeaderPHB.png');
+@partCoverHeaderDMG : url('/assets/partCoverHeaderDMG.svg');
+@insideCoverMask : url('/assets/insideCoverMask.png');
+@backCover : url('/assets/backCover.png');
+@scriptBorder : url('/assets/scriptBorder.png');
// Watercolor Images
@watercolor1 : url('/assets/watercolor/watercolor1.png');
diff --git a/themes/assets/backCover.png b/themes/assets/backCover.png
new file mode 100644
index 000000000..5c6a14d25
Binary files /dev/null and b/themes/assets/backCover.png differ
diff --git a/themes/assets/coverPageBanner.svg b/themes/assets/coverPageBanner.svg
new file mode 100644
index 000000000..8e7c4acc2
--- /dev/null
+++ b/themes/assets/coverPageBanner.svg
@@ -0,0 +1 @@
+Asset 2
\ No newline at end of file
diff --git a/themes/assets/dragonBackground.png b/themes/assets/dragonBackground.png
new file mode 100644
index 000000000..987e36e4d
Binary files /dev/null and b/themes/assets/dragonBackground.png differ
diff --git a/themes/assets/horizontalRule.svg b/themes/assets/horizontalRule.svg
new file mode 100644
index 000000000..9fce47809
--- /dev/null
+++ b/themes/assets/horizontalRule.svg
@@ -0,0 +1 @@
+Asset 2
\ No newline at end of file
diff --git a/themes/assets/insideCoverMask.png b/themes/assets/insideCoverMask.png
new file mode 100644
index 000000000..d28a93f70
Binary files /dev/null and b/themes/assets/insideCoverMask.png differ
diff --git a/themes/assets/naturalCritLogoRed.svg b/themes/assets/naturalCritLogoRed.svg
new file mode 100644
index 000000000..71cc40a97
--- /dev/null
+++ b/themes/assets/naturalCritLogoRed.svg
@@ -0,0 +1 @@
+NaturalCritLogo
\ No newline at end of file
diff --git a/themes/assets/naturalCritLogoWhite.svg b/themes/assets/naturalCritLogoWhite.svg
new file mode 100644
index 000000000..56b820776
--- /dev/null
+++ b/themes/assets/naturalCritLogoWhite.svg
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+ NaturalCritLogo
+
+
+
+
+
+
diff --git a/themes/assets/partCoverHeaderDMG.svg b/themes/assets/partCoverHeaderDMG.svg
new file mode 100644
index 000000000..b7defc541
--- /dev/null
+++ b/themes/assets/partCoverHeaderDMG.svg
@@ -0,0 +1 @@
+Asset 2
\ No newline at end of file
diff --git a/themes/assets/partCoverHeaderPHB.png b/themes/assets/partCoverHeaderPHB.png
new file mode 100644
index 000000000..f359668ba
Binary files /dev/null and b/themes/assets/partCoverHeaderPHB.png differ
diff --git a/themes/assets/scriptBorder.png b/themes/assets/scriptBorder.png
new file mode 100644
index 000000000..05d481a97
Binary files /dev/null and b/themes/assets/scriptBorder.png differ
diff --git a/themes/assets/waterColorMasks/center/0001.webp b/themes/assets/waterColorMasks/center/0001.webp
new file mode 100644
index 000000000..7e3d73476
Binary files /dev/null and b/themes/assets/waterColorMasks/center/0001.webp differ
diff --git a/themes/assets/waterColorMasks/center/0002.webp b/themes/assets/waterColorMasks/center/0002.webp
new file mode 100644
index 000000000..d60bbeaf5
Binary files /dev/null and b/themes/assets/waterColorMasks/center/0002.webp differ
diff --git a/themes/assets/waterColorMasks/center/0003.webp b/themes/assets/waterColorMasks/center/0003.webp
new file mode 100644
index 000000000..69d96c4cc
Binary files /dev/null and b/themes/assets/waterColorMasks/center/0003.webp differ
diff --git a/themes/assets/waterColorMasks/center/0004.webp b/themes/assets/waterColorMasks/center/0004.webp
new file mode 100644
index 000000000..781de4fac
Binary files /dev/null and b/themes/assets/waterColorMasks/center/0004.webp differ
diff --git a/themes/assets/waterColorMasks/center/0005.webp b/themes/assets/waterColorMasks/center/0005.webp
new file mode 100644
index 000000000..e6d14b48a
Binary files /dev/null and b/themes/assets/waterColorMasks/center/0005.webp differ
diff --git a/themes/assets/waterColorMasks/center/0006.webp b/themes/assets/waterColorMasks/center/0006.webp
new file mode 100644
index 000000000..e4b606d68
Binary files /dev/null and b/themes/assets/waterColorMasks/center/0006.webp differ
diff --git a/themes/assets/waterColorMasks/center/0007.webp b/themes/assets/waterColorMasks/center/0007.webp
new file mode 100644
index 000000000..1af90ce25
Binary files /dev/null and b/themes/assets/waterColorMasks/center/0007.webp differ
diff --git a/themes/assets/waterColorMasks/center/0008.webp b/themes/assets/waterColorMasks/center/0008.webp
new file mode 100644
index 000000000..4487aff50
Binary files /dev/null and b/themes/assets/waterColorMasks/center/0008.webp differ
diff --git a/themes/assets/waterColorMasks/center/0009.webp b/themes/assets/waterColorMasks/center/0009.webp
new file mode 100644
index 000000000..3524c76b8
Binary files /dev/null and b/themes/assets/waterColorMasks/center/0009.webp differ
diff --git a/themes/assets/waterColorMasks/center/0010.webp b/themes/assets/waterColorMasks/center/0010.webp
new file mode 100644
index 000000000..ea7da913f
Binary files /dev/null and b/themes/assets/waterColorMasks/center/0010.webp differ
diff --git a/themes/assets/waterColorMasks/center/0011.webp b/themes/assets/waterColorMasks/center/0011.webp
new file mode 100644
index 000000000..74bb72526
Binary files /dev/null and b/themes/assets/waterColorMasks/center/0011.webp differ
diff --git a/themes/assets/waterColorMasks/center/0012.webp b/themes/assets/waterColorMasks/center/0012.webp
new file mode 100644
index 000000000..5ee3e668f
Binary files /dev/null and b/themes/assets/waterColorMasks/center/0012.webp differ
diff --git a/themes/assets/waterColorMasks/center/0013.webp b/themes/assets/waterColorMasks/center/0013.webp
new file mode 100644
index 000000000..cdc6cec28
Binary files /dev/null and b/themes/assets/waterColorMasks/center/0013.webp differ
diff --git a/themes/assets/waterColorMasks/center/0014.webp b/themes/assets/waterColorMasks/center/0014.webp
new file mode 100644
index 000000000..0801848c5
Binary files /dev/null and b/themes/assets/waterColorMasks/center/0014.webp differ
diff --git a/themes/assets/waterColorMasks/center/0015.webp b/themes/assets/waterColorMasks/center/0015.webp
new file mode 100644
index 000000000..90f36fe21
Binary files /dev/null and b/themes/assets/waterColorMasks/center/0015.webp differ
diff --git a/themes/assets/waterColorMasks/center/0016.webp b/themes/assets/waterColorMasks/center/0016.webp
new file mode 100644
index 000000000..0d7e68597
Binary files /dev/null and b/themes/assets/waterColorMasks/center/0016.webp differ
diff --git a/themes/assets/waterColorMasks/center/special.webp b/themes/assets/waterColorMasks/center/special.webp
new file mode 100644
index 000000000..1a3f6240a
Binary files /dev/null and b/themes/assets/waterColorMasks/center/special.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0001.webp b/themes/assets/waterColorMasks/corner/0001.webp
new file mode 100644
index 000000000..65830dbf1
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0001.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0002.webp b/themes/assets/waterColorMasks/corner/0002.webp
new file mode 100644
index 000000000..250a94b38
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0002.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0003.webp b/themes/assets/waterColorMasks/corner/0003.webp
new file mode 100644
index 000000000..6a6c8e660
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0003.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0004.webp b/themes/assets/waterColorMasks/corner/0004.webp
new file mode 100644
index 000000000..d1fcc49f0
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0004.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0005.webp b/themes/assets/waterColorMasks/corner/0005.webp
new file mode 100644
index 000000000..3fd1f0d8b
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0005.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0006.webp b/themes/assets/waterColorMasks/corner/0006.webp
new file mode 100644
index 000000000..f5303afa7
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0006.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0007.webp b/themes/assets/waterColorMasks/corner/0007.webp
new file mode 100644
index 000000000..6d8d9b9a3
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0007.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0008.webp b/themes/assets/waterColorMasks/corner/0008.webp
new file mode 100644
index 000000000..a732854e1
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0008.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0009.webp b/themes/assets/waterColorMasks/corner/0009.webp
new file mode 100644
index 000000000..c84e69a07
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0009.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0010.webp b/themes/assets/waterColorMasks/corner/0010.webp
new file mode 100644
index 000000000..8fba1a496
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0010.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0011.webp b/themes/assets/waterColorMasks/corner/0011.webp
new file mode 100644
index 000000000..c6526f9d7
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0011.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0012.webp b/themes/assets/waterColorMasks/corner/0012.webp
new file mode 100644
index 000000000..0fafd03db
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0012.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0013.webp b/themes/assets/waterColorMasks/corner/0013.webp
new file mode 100644
index 000000000..040234864
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0013.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0014.webp b/themes/assets/waterColorMasks/corner/0014.webp
new file mode 100644
index 000000000..fa04254b2
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0014.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0015.webp b/themes/assets/waterColorMasks/corner/0015.webp
new file mode 100644
index 000000000..f64bdc954
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0015.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0016.webp b/themes/assets/waterColorMasks/corner/0016.webp
new file mode 100644
index 000000000..f727e56b5
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0016.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0017.webp b/themes/assets/waterColorMasks/corner/0017.webp
new file mode 100644
index 000000000..00c6a2ac2
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0017.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0018.webp b/themes/assets/waterColorMasks/corner/0018.webp
new file mode 100644
index 000000000..b9bd82283
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0018.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0019.webp b/themes/assets/waterColorMasks/corner/0019.webp
new file mode 100644
index 000000000..452268aba
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0019.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0020.webp b/themes/assets/waterColorMasks/corner/0020.webp
new file mode 100644
index 000000000..d8f9fbf60
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0020.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0021.webp b/themes/assets/waterColorMasks/corner/0021.webp
new file mode 100644
index 000000000..08343ea74
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0021.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0022.webp b/themes/assets/waterColorMasks/corner/0022.webp
new file mode 100644
index 000000000..6f64571e0
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0022.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0023.webp b/themes/assets/waterColorMasks/corner/0023.webp
new file mode 100644
index 000000000..2c88031c5
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0023.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0024.webp b/themes/assets/waterColorMasks/corner/0024.webp
new file mode 100644
index 000000000..a187a75b0
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0024.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0025.webp b/themes/assets/waterColorMasks/corner/0025.webp
new file mode 100644
index 000000000..4511b6303
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0025.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0026.webp b/themes/assets/waterColorMasks/corner/0026.webp
new file mode 100644
index 000000000..a5dd080ae
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0026.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0027.webp b/themes/assets/waterColorMasks/corner/0027.webp
new file mode 100644
index 000000000..d7198530c
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0027.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0028.webp b/themes/assets/waterColorMasks/corner/0028.webp
new file mode 100644
index 000000000..5b836ace9
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0028.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0029.webp b/themes/assets/waterColorMasks/corner/0029.webp
new file mode 100644
index 000000000..ecf4200fc
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0029.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0030.webp b/themes/assets/waterColorMasks/corner/0030.webp
new file mode 100644
index 000000000..73f2c954a
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0030.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0031.webp b/themes/assets/waterColorMasks/corner/0031.webp
new file mode 100644
index 000000000..9fc1785a9
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0031.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0032.webp b/themes/assets/waterColorMasks/corner/0032.webp
new file mode 100644
index 000000000..497aaa201
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0032.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0033.webp b/themes/assets/waterColorMasks/corner/0033.webp
new file mode 100644
index 000000000..6086a5576
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0033.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0034.webp b/themes/assets/waterColorMasks/corner/0034.webp
new file mode 100644
index 000000000..4e8885f2e
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0034.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0035.webp b/themes/assets/waterColorMasks/corner/0035.webp
new file mode 100644
index 000000000..f010e194f
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0035.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0036.webp b/themes/assets/waterColorMasks/corner/0036.webp
new file mode 100644
index 000000000..e662511d7
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0036.webp differ
diff --git a/themes/assets/waterColorMasks/corner/0037.webp b/themes/assets/waterColorMasks/corner/0037.webp
new file mode 100644
index 000000000..9e90d65c4
Binary files /dev/null and b/themes/assets/waterColorMasks/corner/0037.webp differ
diff --git a/themes/assets/waterColorMasks/edge/0001.webp b/themes/assets/waterColorMasks/edge/0001.webp
new file mode 100644
index 000000000..6138a1a1b
Binary files /dev/null and b/themes/assets/waterColorMasks/edge/0001.webp differ
diff --git a/themes/assets/waterColorMasks/edge/0002.webp b/themes/assets/waterColorMasks/edge/0002.webp
new file mode 100644
index 000000000..15766829b
Binary files /dev/null and b/themes/assets/waterColorMasks/edge/0002.webp differ
diff --git a/themes/assets/waterColorMasks/edge/0003.webp b/themes/assets/waterColorMasks/edge/0003.webp
new file mode 100644
index 000000000..ef77e7577
Binary files /dev/null and b/themes/assets/waterColorMasks/edge/0003.webp differ
diff --git a/themes/assets/waterColorMasks/edge/0004.webp b/themes/assets/waterColorMasks/edge/0004.webp
new file mode 100644
index 000000000..d18da828b
Binary files /dev/null and b/themes/assets/waterColorMasks/edge/0004.webp differ
diff --git a/themes/assets/waterColorMasks/edge/0005.webp b/themes/assets/waterColorMasks/edge/0005.webp
new file mode 100644
index 000000000..f9c9c12e7
Binary files /dev/null and b/themes/assets/waterColorMasks/edge/0005.webp differ
diff --git a/themes/assets/waterColorMasks/edge/0006.webp b/themes/assets/waterColorMasks/edge/0006.webp
new file mode 100644
index 000000000..f09e74316
Binary files /dev/null and b/themes/assets/waterColorMasks/edge/0006.webp differ
diff --git a/themes/assets/waterColorMasks/edge/0007.webp b/themes/assets/waterColorMasks/edge/0007.webp
new file mode 100644
index 000000000..197915e90
Binary files /dev/null and b/themes/assets/waterColorMasks/edge/0007.webp differ
diff --git a/themes/assets/waterColorMasks/edge/0008.webp b/themes/assets/waterColorMasks/edge/0008.webp
new file mode 100644
index 000000000..bf6c90229
Binary files /dev/null and b/themes/assets/waterColorMasks/edge/0008.webp differ
diff --git a/themes/assets/waterColorMasks/missingImage.png b/themes/assets/waterColorMasks/missingImage.png
new file mode 100644
index 000000000..08dcb816c
Binary files /dev/null and b/themes/assets/waterColorMasks/missingImage.png differ
diff --git a/themes/fonts/5e/Davek.woff2 b/themes/fonts/5e/Davek.woff2
new file mode 100644
index 000000000..69a7de83c
Binary files /dev/null and b/themes/fonts/5e/Davek.woff2 differ
diff --git a/themes/fonts/5e/Iokharic.woff2 b/themes/fonts/5e/Iokharic.woff2
new file mode 100644
index 000000000..2ceb7c6b7
Binary files /dev/null and b/themes/fonts/5e/Iokharic.woff2 differ
diff --git a/themes/fonts/5e/Martel Sans Black.woff2 b/themes/fonts/5e/Martel Sans Black.woff2
new file mode 100644
index 000000000..44580467d
Binary files /dev/null and b/themes/fonts/5e/Martel Sans Black.woff2 differ
diff --git a/themes/fonts/5e/Nodesto Caps Condensed.woff2 b/themes/fonts/5e/Nodesto Caps Condensed.woff2
index bdb21d4cd..335079b7e 100644
Binary files a/themes/fonts/5e/Nodesto Caps Condensed.woff2 and b/themes/fonts/5e/Nodesto Caps Condensed.woff2 differ
diff --git a/themes/fonts/5e/Nodesto Caps Wide.woff2 b/themes/fonts/5e/Nodesto Caps Wide.woff2
new file mode 100644
index 000000000..d50a19915
Binary files /dev/null and b/themes/fonts/5e/Nodesto Caps Wide.woff2 differ
diff --git a/themes/fonts/5e/Overpass Medium.woff2 b/themes/fonts/5e/Overpass Medium.woff2
new file mode 100644
index 000000000..74951a813
Binary files /dev/null and b/themes/fonts/5e/Overpass Medium.woff2 differ
diff --git a/themes/fonts/5e/Rellanic.woff2 b/themes/fonts/5e/Rellanic.woff2
new file mode 100644
index 000000000..add898f45
Binary files /dev/null and b/themes/fonts/5e/Rellanic.woff2 differ
diff --git a/themes/fonts/5e/Scaly Sans Caps.woff2 b/themes/fonts/5e/Scaly Sans Caps.woff2
index 38ee910c8..95231a609 100644
Binary files a/themes/fonts/5e/Scaly Sans Caps.woff2 and b/themes/fonts/5e/Scaly Sans Caps.woff2 differ
diff --git a/themes/fonts/5e/fonts.less b/themes/fonts/5e/fonts.less
index f5118a7cc..8f089b51c 100644
--- a/themes/fonts/5e/fonts.less
+++ b/themes/fonts/5e/fonts.less
@@ -106,3 +106,37 @@
font-weight: bold;
font-style: italic;
}
+
+@font-face {
+ font-family: NodestoCapsWide;
+ src: url('../../../fonts/5e/Nodesto Caps Wide.woff2');
+ font-weight: normal;
+ font-style: normal
+}
+
+@font-face {
+ font-family: Overpass;
+ src: url('../../../fonts/5e/Overpass Medium.woff2');
+ font-weight: 500;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: Davek;
+ src: url('../../../fonts/5e/Davek.woff2');
+ font-weight: 500;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: Iokharic;
+ src: url('../../../fonts/5e/Iokharic.woff2');
+ font-weight: 500;
+ font-style: normal;
+}
+@font-face {
+ font-family: Rellanic;
+ src: url('../../../fonts/5e/Rellanic.woff2');
+ font-weight: 500;
+ font-style: normal;
+}