Merge branch 'master' into pr/2661
@@ -48,7 +48,7 @@ jobs:
|
|||||||
- image: cimg/node:16.11.0
|
- image: cimg/node:16.11.0
|
||||||
|
|
||||||
working_directory: ~/homebrewery
|
working_directory: ~/homebrewery
|
||||||
parallelism: 4
|
parallelism: 1
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
@@ -61,15 +61,15 @@ jobs:
|
|||||||
- run:
|
- run:
|
||||||
name: Test - Basic
|
name: Test - Basic
|
||||||
command: npm run test:basic
|
command: npm run test:basic
|
||||||
- run:
|
|
||||||
name: Test - Coverage
|
|
||||||
command: npm run test:coverage
|
|
||||||
- run:
|
- run:
|
||||||
name: Test - Mustache Spans
|
name: Test - Mustache Spans
|
||||||
command: npm run test:mustache-span
|
command: npm run test:mustache-span
|
||||||
- run:
|
- run:
|
||||||
name: Test - Routes
|
name: Test - Routes
|
||||||
command: npm run test:route
|
command: npm run test:route
|
||||||
|
- run:
|
||||||
|
name: Test - Coverage
|
||||||
|
command: npm run test:coverage
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
build_and_test:
|
build_and_test:
|
||||||
|
|||||||
2
.gitignore
vendored
@@ -12,3 +12,5 @@ todo.md
|
|||||||
startDB.bat
|
startDB.bat
|
||||||
startMViewer.bat
|
startMViewer.bat
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
|
coverage
|
||||||
|
|||||||
100
changelog.md
@@ -1,4 +1,23 @@
|
|||||||
```css
|
```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 {
|
h5 {
|
||||||
font-size: .35cm !important;
|
font-size: .35cm !important;
|
||||||
}
|
}
|
||||||
@@ -61,7 +80,86 @@ pre {
|
|||||||
## changelog
|
## changelog
|
||||||
For a full record of development, visit our [Github Page](https://github.com/naturalcrit/homebrewery).
|
For a full record of development, visit our [Github Page](https://github.com/naturalcrit/homebrewery).
|
||||||
|
|
||||||
### Friday 23/01/2023 - v3.6.0
|
### XXXXday DD/MM/2023 - v3.8.0
|
||||||
|
{{taskList
|
||||||
|
##### 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 automatically receiving the `target=_self` attribute
|
||||||
|
|
||||||
|
Fixes issues [#2680](https://github.com/naturalcrit/homebrewery/issues/2680)
|
||||||
|
}}
|
||||||
|
|
||||||
|
### 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 text selectable in PDFs again.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
Fixes issues [#2674](https://github.com/naturalcrit/homebrewery/issues/2674)
|
||||||
|
}}
|
||||||
|
|
||||||
|
### Monday 23/01/2023 - v3.6.0
|
||||||
{{taskList
|
{{taskList
|
||||||
##### calculuschild
|
##### calculuschild
|
||||||
|
|
||||||
|
|||||||
129
client/components/combobox.jsx
Normal file
@@ -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 (
|
||||||
|
<div className='dropdown-input item'
|
||||||
|
onMouseEnter={this.props.trigger == 'hover' ? ()=>{this.handleDropdown(true);} : undefined}
|
||||||
|
onClick= {this.props.trigger == 'click' ? ()=>{this.handleDropdown(true);} : undefined}>
|
||||||
|
<input
|
||||||
|
type='text'
|
||||||
|
onChange={(e)=>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));
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
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 (
|
||||||
|
<div className='dropdown-options'>
|
||||||
|
{dropdownChildren}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
render : function () {
|
||||||
|
const dropdownChildren = this.state.options.map((child, i)=>{
|
||||||
|
const clone = React.cloneElement(child, { onClick: (e)=>this.handleSelect(e) });
|
||||||
|
return clone;
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<div className={`dropdown-container ${this.props.className}`}
|
||||||
|
ref='dropdown'
|
||||||
|
onMouseLeave={this.props.trigger == 'hover' ? ()=>{this.handleDropdown(false);} : undefined}>
|
||||||
|
{this.renderTextInput()}
|
||||||
|
{this.renderDropdown(dropdownChildren)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Combobox;
|
||||||
50
client/components/combobox.less
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -27,6 +27,7 @@ const BrewRenderer = createClass({
|
|||||||
style : '',
|
style : '',
|
||||||
renderer : 'legacy',
|
renderer : 'legacy',
|
||||||
theme : '5ePHB',
|
theme : '5ePHB',
|
||||||
|
lang : '',
|
||||||
errors : []
|
errors : []
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -134,7 +135,8 @@ const BrewRenderer = createClass({
|
|||||||
|
|
||||||
renderStyle : function() {
|
renderStyle : function() {
|
||||||
if(!this.props.style) return;
|
if(!this.props.style) return;
|
||||||
return <div style={{ display: 'none' }} dangerouslySetInnerHTML={{ __html: `<style>@layer styleTab {\n${this.props.style}\n} </style>` }} />;
|
//return <div style={{ display: 'none' }} dangerouslySetInnerHTML={{ __html: `<style>@layer styleTab {\n${this.props.style}\n} </style>` }} />;
|
||||||
|
return <div style={{ display: 'none' }} dangerouslySetInnerHTML={{ __html: `<style>\n${this.props.style}\n</style>` }} />;
|
||||||
},
|
},
|
||||||
|
|
||||||
renderPage : function(pageText, index){
|
renderPage : function(pageText, index){
|
||||||
@@ -189,7 +191,6 @@ const BrewRenderer = createClass({
|
|||||||
const rendererPath = this.props.renderer == 'V3' ? 'V3' : 'Legacy';
|
const rendererPath = this.props.renderer == 'V3' ? 'V3' : 'Legacy';
|
||||||
const themePath = this.props.theme ?? '5ePHB';
|
const themePath = this.props.theme ?? '5ePHB';
|
||||||
const baseThemePath = Themes[rendererPath][themePath].baseTheme;
|
const baseThemePath = Themes[rendererPath][themePath].baseTheme;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{!this.state.isMounted
|
{!this.state.isMounted
|
||||||
@@ -222,7 +223,7 @@ const BrewRenderer = createClass({
|
|||||||
&&
|
&&
|
||||||
<>
|
<>
|
||||||
{this.renderStyle()}
|
{this.renderStyle()}
|
||||||
<div className='pages' ref='pages'>
|
<div className='pages' ref='pages' lang={`${this.props.lang || 'en'}`}>
|
||||||
{this.renderPages()}
|
{this.renderPages()}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ const _ = require('lodash');
|
|||||||
const cx = require('classnames');
|
const cx = require('classnames');
|
||||||
const request = require('../../utils/request-middleware.js');
|
const request = require('../../utils/request-middleware.js');
|
||||||
const Nav = require('naturalcrit/nav/nav.jsx');
|
const Nav = require('naturalcrit/nav/nav.jsx');
|
||||||
|
const Combobox = require('client/components/combobox.jsx');
|
||||||
const StringArrayEditor = require('../stringArrayEditor/stringArrayEditor.jsx');
|
const StringArrayEditor = require('../stringArrayEditor/stringArrayEditor.jsx');
|
||||||
|
|
||||||
const Themes = require('themes/themes.json');
|
const Themes = require('themes/themes.json');
|
||||||
@@ -35,7 +36,8 @@ const MetadataEditor = createClass({
|
|||||||
authors : [],
|
authors : [],
|
||||||
systems : [],
|
systems : [],
|
||||||
renderer : 'legacy',
|
renderer : 'legacy',
|
||||||
theme : '5ePHB'
|
theme : '5ePHB',
|
||||||
|
lang : 'en'
|
||||||
},
|
},
|
||||||
onChange : ()=>{},
|
onChange : ()=>{},
|
||||||
reportError : ()=>{}
|
reportError : ()=>{}
|
||||||
@@ -76,6 +78,7 @@ const MetadataEditor = createClass({
|
|||||||
const errMessage = validationErr.map((err)=>{
|
const errMessage = validationErr.map((err)=>{
|
||||||
return `- ${err}`;
|
return `- ${err}`;
|
||||||
}).join('\n');
|
}).join('\n');
|
||||||
|
|
||||||
callIfExists(e.target, 'setCustomValidity', errMessage);
|
callIfExists(e.target, 'setCustomValidity', errMessage);
|
||||||
callIfExists(e.target, 'reportValidity');
|
callIfExists(e.target, 'reportValidity');
|
||||||
}
|
}
|
||||||
@@ -111,6 +114,11 @@ const MetadataEditor = createClass({
|
|||||||
this.props.onChange(this.props.metadata);
|
this.props.onChange(this.props.metadata);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handleLanguage : function(languageCode){
|
||||||
|
this.props.metadata.lang = languageCode;
|
||||||
|
this.props.onChange(this.props.metadata);
|
||||||
|
},
|
||||||
|
|
||||||
handleDelete : function(){
|
handleDelete : function(){
|
||||||
if(this.props.metadata.authors && this.props.metadata.authors.length <= 1){
|
if(this.props.metadata.authors && this.props.metadata.authors.length <= 1){
|
||||||
if(!confirm('Are you sure you want to delete this brew? Because you are the only owner of this brew, the document will be deleted permanently.')) return;
|
if(!confirm('Are you sure you want to delete this brew? Because you are the only owner of this brew, the document will be deleted permanently.')) return;
|
||||||
@@ -224,6 +232,47 @@ const MetadataEditor = createClass({
|
|||||||
</div>;
|
</div>;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
renderLanguageDropdown : function(){
|
||||||
|
const langCodes = ['en', 'de', 'de-ch', 'fr', 'ja', 'es', 'it', 'sv', 'ru', 'zh-Hans', 'zh-Hant'];
|
||||||
|
const listLanguages = ()=>{
|
||||||
|
return _.map(langCodes.sort(), (code, index)=>{
|
||||||
|
const localName = new Intl.DisplayNames([code], { type: 'language' });
|
||||||
|
const englishName = new Intl.DisplayNames('en', { type: 'language' });
|
||||||
|
return <div className='item' title={`${englishName.of(code)}`} key={`${index}`} data-value={`${code}`} data-detail={`${localName.of(code)}`}>
|
||||||
|
{`${code}`}
|
||||||
|
<div className='detail'>{`${localName.of(code)}`}</div>
|
||||||
|
</div>;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const debouncedHandleFieldChange = _.debounce(this.handleFieldChange, 500);
|
||||||
|
|
||||||
|
return <div className='field language'>
|
||||||
|
<label>language</label>
|
||||||
|
<div className='value'>
|
||||||
|
<Combobox trigger='click'
|
||||||
|
className='language-dropdown'
|
||||||
|
default={this.props.metadata.lang || ''}
|
||||||
|
placeholder='en'
|
||||||
|
onSelect={(value)=>this.handleLanguage(value)}
|
||||||
|
onEntry={(e)=>{
|
||||||
|
e.target.setCustomValidity(''); //Clear the validation popup while typing
|
||||||
|
debouncedHandleFieldChange('lang', e);
|
||||||
|
}}
|
||||||
|
options={listLanguages()}
|
||||||
|
autoSuggest={{
|
||||||
|
suggestMethod : 'startsWith',
|
||||||
|
clearAutoSuggestOnClick : true,
|
||||||
|
filterOn : ['data-value', 'data-detail', 'title']
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
</Combobox>
|
||||||
|
<small>Sets the HTML Lang property for your brew. May affect hyphenation or spellcheck.</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>;
|
||||||
|
},
|
||||||
|
|
||||||
renderRenderOptions : function(){
|
renderRenderOptions : function(){
|
||||||
if(!global.enable_v3) return;
|
if(!global.enable_v3) return;
|
||||||
|
|
||||||
@@ -301,6 +350,8 @@ const MetadataEditor = createClass({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{this.renderLanguageDropdown()}
|
||||||
|
|
||||||
{this.renderThemeDropdown()}
|
{this.renderThemeDropdown()}
|
||||||
|
|
||||||
{this.renderRenderOptions()}
|
{this.renderRenderOptions()}
|
||||||
@@ -315,7 +366,7 @@ const MetadataEditor = createClass({
|
|||||||
validators={[(v)=>!this.props.metadata.authors?.includes(v)]}
|
validators={[(v)=>!this.props.metadata.authors?.includes(v)]}
|
||||||
placeholder='invite author' unique={true}
|
placeholder='invite author' unique={true}
|
||||||
values={this.props.metadata.invitedAuthors}
|
values={this.props.metadata.invitedAuthors}
|
||||||
notes={['Invited authors are case sensitive.', 'After adding an invited author, send them the edit link. There, they can choose to accept or decline the invitation.']}
|
notes={['Invited author usernames are case sensitive.', 'After adding an invited author, send them the edit link. There, they can choose to accept or decline the invitation.']}
|
||||||
onChange={(e)=>this.handleFieldChange('invitedAuthors', e)}/>
|
onChange={(e)=>this.handleFieldChange('invitedAuthors', e)}/>
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|||||||
@@ -36,11 +36,15 @@
|
|||||||
flex: 5 0 200px;
|
flex: 5 0 200px;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.field{
|
.field{
|
||||||
display : flex;
|
display : flex;
|
||||||
flex-wrap : wrap;
|
flex-wrap : wrap;
|
||||||
width : 100%;
|
width : 100%;
|
||||||
min-width : 200px;
|
min-width : 200px;
|
||||||
|
position : relative;
|
||||||
&>label{
|
&>label{
|
||||||
width : 80px;
|
width : 80px;
|
||||||
font-size : 11px;
|
font-size : 11px;
|
||||||
@@ -57,6 +61,9 @@
|
|||||||
}
|
}
|
||||||
input[type='text'], textarea {
|
input[type='text'], textarea {
|
||||||
border : 1px solid gray;
|
border : 1px solid gray;
|
||||||
|
&:focus {
|
||||||
|
outline: 1px solid #444;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&.thumbnail{
|
&.thumbnail{
|
||||||
height : 1.4em;
|
height : 1.4em;
|
||||||
@@ -88,9 +95,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.language .language-dropdown {
|
||||||
|
max-width : 150px;
|
||||||
|
z-index : 200;
|
||||||
|
}
|
||||||
small {
|
small {
|
||||||
font-size : 0.6em;
|
font-size : 0.6em;
|
||||||
font-style : italic;
|
font-style : italic;
|
||||||
|
line-height : 1.4em;
|
||||||
|
display : inline-block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +172,7 @@
|
|||||||
.navDropdownContainer {
|
.navDropdownContainer {
|
||||||
background-color : white;
|
background-color : white;
|
||||||
position : relative;
|
position : relative;
|
||||||
z-index : 500;
|
z-index : 100;
|
||||||
&.disabled {
|
&.disabled {
|
||||||
font-style :italic;
|
font-style :italic;
|
||||||
font-style : italic;
|
font-style : italic;
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
language : [
|
lang : [
|
||||||
(value)=>{
|
(value)=>{
|
||||||
return new RegExp(/[a-z]{2,3}(-.*)?/).test(value || '') === false ? 'Invalid language code.' : null;
|
return new RegExp(/^([a-zA-Z]{2,3})(-[a-zA-Z]{4})?(-(?:[0-9]{3}|[a-zA-Z]{2}))?$/).test(value) === false && (value.length > 0) ? 'Invalid language code.' : null;
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -171,7 +171,8 @@ const SnippetGroup = createClass({
|
|||||||
return _.map(snippets, (snippet)=>{
|
return _.map(snippets, (snippet)=>{
|
||||||
return <div className='snippet' key={snippet.name} onClick={(e)=>this.handleSnippetClick(e, snippet)}>
|
return <div className='snippet' key={snippet.name} onClick={(e)=>this.handleSnippetClick(e, snippet)}>
|
||||||
<i className={snippet.icon} />
|
<i className={snippet.icon} />
|
||||||
{snippet.name}
|
<span className='name'>{snippet.name}</span>
|
||||||
|
{snippet.experimental && <span className='beta'>beta</span>}
|
||||||
{snippet.subsnippets && <>
|
{snippet.subsnippets && <>
|
||||||
<i className='fas fa-caret-right'></i>
|
<i className='fas fa-caret-right'></i>
|
||||||
<div className='dropdown side'>
|
<div className='dropdown side'>
|
||||||
|
|||||||
@@ -96,20 +96,36 @@
|
|||||||
padding : 0px;
|
padding : 0px;
|
||||||
background-color : #ddd;
|
background-color : #ddd;
|
||||||
.snippet{
|
.snippet{
|
||||||
|
position: relative;
|
||||||
.animate(background-color);
|
.animate(background-color);
|
||||||
width : max-content;
|
display : flex;
|
||||||
padding : 5px;
|
align-items : center;
|
||||||
cursor : pointer;
|
min-width : max-content;
|
||||||
font-size : 10px;
|
padding : 5px;
|
||||||
|
cursor : pointer;
|
||||||
|
font-size : 10px;
|
||||||
i{
|
i{
|
||||||
margin-right : 8px;
|
margin-right : 8px;
|
||||||
font-size : 1.2em;
|
font-size : 1.2em;
|
||||||
height : 1.2em;
|
height : 1.2em;
|
||||||
&~i{
|
&~i{
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
margin-left: 8px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.name {
|
||||||
|
margin-right : auto;
|
||||||
|
}
|
||||||
|
.beta {
|
||||||
|
color : white;
|
||||||
|
padding : 4px 6px;
|
||||||
|
line-height : 1em;
|
||||||
|
margin-left : 5px;
|
||||||
|
align-self : center;
|
||||||
|
background : grey;
|
||||||
|
border-radius : 12px;
|
||||||
|
font-family : monospace;
|
||||||
|
}
|
||||||
&:hover{
|
&:hover{
|
||||||
background-color : #999;
|
background-color : #999;
|
||||||
&>.dropdown{
|
&>.dropdown{
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 305 KiB |
8
client/homebrew/googleDrive.svg
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<svg viewBox="0 0 87.3 78" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m6.6 66.85 3.85 6.65c.8 1.4 1.95 2.5 3.3 3.3l13.75-23.8h-27.5c0 1.55.4 3.1 1.2 4.5z" fill="#0066da"/>
|
||||||
|
<path d="m43.65 25-13.75-23.8c-1.35.8-2.5 1.9-3.3 3.3l-25.4 44a9.06 9.06 0 0 0 -1.2 4.5h27.5z" fill="#00ac47"/>
|
||||||
|
<path d="m73.55 76.8c1.35-.8 2.5-1.9 3.3-3.3l1.6-2.75 7.65-13.25c.8-1.4 1.2-2.95 1.2-4.5h-27.502l5.852 11.5z" fill="#ea4335"/>
|
||||||
|
<path d="m43.65 25 13.75-23.8c-1.35-.8-2.9-1.2-4.5-1.2h-18.5c-1.6 0-3.15.45-4.5 1.2z" fill="#00832d"/>
|
||||||
|
<path d="m59.8 53h-32.3l-13.75 23.8c1.35.8 2.9 1.2 4.5 1.2h50.8c1.6 0 3.15-.45 4.5-1.2z" fill="#2684fc"/>
|
||||||
|
<path d="m73.4 26.5-12.7-22c-.8-1.4-1.95-2.5-3.3-3.3l-13.75 23.8 16.15 28h27.45c0-1.55-.4-3.1-1.2-4.5z" fill="#ffba00"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 755 B |
|
Before Width: | Height: | Size: 17 KiB |
@@ -47,6 +47,7 @@ const Homebrew = createClass({
|
|||||||
editId : null,
|
editId : null,
|
||||||
createdAt : null,
|
createdAt : null,
|
||||||
updatedAt : null,
|
updatedAt : null,
|
||||||
|
lang : ''
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ const Account = createClass({
|
|||||||
if(global.account){
|
if(global.account){
|
||||||
return <Nav.dropdown>
|
return <Nav.dropdown>
|
||||||
<Nav.item
|
<Nav.item
|
||||||
className='account'
|
className='account username'
|
||||||
color='orange'
|
color='orange'
|
||||||
icon='fas fa-user'
|
icon='fas fa-user'
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -187,4 +187,7 @@
|
|||||||
.account.navItem{
|
.account.navItem{
|
||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
}
|
}
|
||||||
|
.account.username.navItem{
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const cx = require('classnames');
|
|||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
const request = require('../../../../utils/request-middleware.js');
|
const request = require('../../../../utils/request-middleware.js');
|
||||||
|
|
||||||
const googleDriveIcon = require('../../../../googleDrive.png');
|
const googleDriveIcon = require('../../../../googleDrive.svg');
|
||||||
const dedent = require('dedent-tabs').default;
|
const dedent = require('dedent-tabs').default;
|
||||||
|
|
||||||
const BrewItem = createClass({
|
const BrewItem = createClass({
|
||||||
|
|||||||
@@ -94,7 +94,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.googleDriveIcon {
|
.googleDriveIcon {
|
||||||
height : 20px;
|
height : 18px;
|
||||||
padding : 0px;
|
padding : 0px;
|
||||||
margin : -5px;
|
margin : -5px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -219,7 +219,7 @@ const ListPage = createClass({
|
|||||||
|
|
||||||
render : function(){
|
render : function(){
|
||||||
return <div className='listPage sitePage'>
|
return <div className='listPage sitePage'>
|
||||||
<style>@layer V3_5ePHB, bundle;</style>
|
{/*<style>@layer V3_5ePHB, bundle;</style>*/}
|
||||||
<link href='/themes/V3/5ePHB/style.css' rel='stylesheet'/>
|
<link href='/themes/V3/5ePHB/style.css' rel='stylesheet'/>
|
||||||
{this.props.navItems}
|
{this.props.navItems}
|
||||||
{this.renderSortOptions()}
|
{this.renderSortOptions()}
|
||||||
|
|||||||
@@ -24,8 +24,7 @@ const Markdown = require('naturalcrit/markdown.js');
|
|||||||
|
|
||||||
const { DEFAULT_BREW_LOAD } = require('../../../../server/brewDefaults.js');
|
const { DEFAULT_BREW_LOAD } = require('../../../../server/brewDefaults.js');
|
||||||
|
|
||||||
const googleDriveActive = require('../../googleDrive.png');
|
const googleDriveIcon = require('../../googleDrive.svg');
|
||||||
const googleDriveInactive = require('../../googleDriveMono.png');
|
|
||||||
|
|
||||||
const SAVE_TIMEOUT = 3000;
|
const SAVE_TIMEOUT = 3000;
|
||||||
|
|
||||||
@@ -222,10 +221,7 @@ const EditPage = createClass({
|
|||||||
|
|
||||||
renderGoogleDriveIcon : function(){
|
renderGoogleDriveIcon : function(){
|
||||||
return <Nav.item className='googleDriveStorage' onClick={this.handleGoogleClick}>
|
return <Nav.item className='googleDriveStorage' onClick={this.handleGoogleClick}>
|
||||||
{this.state.saveGoogle
|
<img src={googleDriveIcon} className={this.state.saveGoogle ? '' : 'inactive'} alt='Google Drive icon'/>
|
||||||
? <img src={googleDriveActive} alt='googleDriveActive'/>
|
|
||||||
: <img src={googleDriveInactive} alt='googleDriveInactive'/>
|
|
||||||
}
|
|
||||||
|
|
||||||
{this.state.confirmGoogleTransfer &&
|
{this.state.confirmGoogleTransfer &&
|
||||||
<div className='errorContainer' onClick={this.closeAlerts}>
|
<div className='errorContainer' onClick={this.closeAlerts}>
|
||||||
@@ -402,7 +398,14 @@ const EditPage = createClass({
|
|||||||
reportError={this.errorReported}
|
reportError={this.errorReported}
|
||||||
renderer={this.state.brew.renderer}
|
renderer={this.state.brew.renderer}
|
||||||
/>
|
/>
|
||||||
<BrewRenderer text={this.state.brew.text} style={this.state.brew.style} renderer={this.state.brew.renderer} theme={this.state.brew.theme} errors={this.state.htmlErrors} />
|
<BrewRenderer
|
||||||
|
text={this.state.brew.text}
|
||||||
|
style={this.state.brew.style}
|
||||||
|
renderer={this.state.brew.renderer}
|
||||||
|
theme={this.state.brew.theme}
|
||||||
|
errors={this.state.htmlErrors}
|
||||||
|
lang={this.state.brew.lang}
|
||||||
|
/>
|
||||||
</SplitPane>
|
</SplitPane>
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
|
|||||||
@@ -18,8 +18,12 @@
|
|||||||
position : relative;
|
position : relative;
|
||||||
}
|
}
|
||||||
.googleDriveStorage img{
|
.googleDriveStorage img{
|
||||||
height : 20px;
|
height : 18px;
|
||||||
padding : 0px;
|
padding : 0px;
|
||||||
margin : -5px;
|
margin : -5px;
|
||||||
|
|
||||||
|
&.inactive {
|
||||||
|
filter: grayscale(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ After clicking the "Print" item in the navbar a new page will open and a print d
|
|||||||
If you want to save ink or have a monochrome printer, add the **PRINT → {{fas,fa-tint}} Ink Friendly** snippet to your brew!
|
If you want to save ink or have a monochrome printer, add the **PRINT → {{fas,fa-tint}} Ink Friendly** snippet to your brew!
|
||||||
}}
|
}}
|
||||||
|
|
||||||
 {position:absolute,bottom:20px,left:130px,width:220px}
|
 {position:absolute,bottom:20px,left:130px,width:220px}
|
||||||
|
|
||||||
{{artist,bottom:160px,left:100px
|
{{artist,bottom:160px,left:100px
|
||||||
##### Homebrew Mug
|
##### Homebrew Mug
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ const NewPage = createClass({
|
|||||||
// brew.description = metaStorage?.description || this.state.brew.description;
|
// brew.description = metaStorage?.description || this.state.brew.description;
|
||||||
brew.renderer = metaStorage?.renderer ?? brew.renderer;
|
brew.renderer = metaStorage?.renderer ?? brew.renderer;
|
||||||
brew.theme = metaStorage?.theme ?? brew.theme;
|
brew.theme = metaStorage?.theme ?? brew.theme;
|
||||||
|
brew.lang = metaStorage?.lang ?? brew.lang;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
brew : brew
|
brew : brew
|
||||||
@@ -70,7 +71,7 @@ const NewPage = createClass({
|
|||||||
localStorage.setItem(BREWKEY, brew.text);
|
localStorage.setItem(BREWKEY, brew.text);
|
||||||
if(brew.style)
|
if(brew.style)
|
||||||
localStorage.setItem(STYLEKEY, brew.style);
|
localStorage.setItem(STYLEKEY, brew.style);
|
||||||
localStorage.setItem(METAKEY, JSON.stringify({ 'renderer': brew.renderer, 'theme': brew.theme }));
|
localStorage.setItem(METAKEY, JSON.stringify({ 'renderer': brew.renderer, 'theme': brew.theme, 'lang': brew.lang }));
|
||||||
},
|
},
|
||||||
componentWillUnmount : function() {
|
componentWillUnmount : function() {
|
||||||
document.removeEventListener('keydown', this.handleControlKeys);
|
document.removeEventListener('keydown', this.handleControlKeys);
|
||||||
@@ -114,13 +115,16 @@ const NewPage = createClass({
|
|||||||
handleMetaChange : function(metadata){
|
handleMetaChange : function(metadata){
|
||||||
this.setState((prevState)=>({
|
this.setState((prevState)=>({
|
||||||
brew : { ...prevState.brew, ...metadata },
|
brew : { ...prevState.brew, ...metadata },
|
||||||
}));
|
}), ()=>{
|
||||||
localStorage.setItem(METAKEY, JSON.stringify({
|
localStorage.setItem(METAKEY, JSON.stringify({
|
||||||
// 'title' : this.state.brew.title,
|
// 'title' : this.state.brew.title,
|
||||||
// 'description' : this.state.brew.description,
|
// 'description' : this.state.brew.description,
|
||||||
'renderer' : this.state.brew.renderer,
|
'renderer' : this.state.brew.renderer,
|
||||||
'theme' : this.state.brew.theme
|
'theme' : this.state.brew.theme,
|
||||||
}));
|
'lang' : this.state.brew.lang
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
;
|
||||||
},
|
},
|
||||||
|
|
||||||
save : async function(){
|
save : async function(){
|
||||||
@@ -211,7 +215,7 @@ const NewPage = createClass({
|
|||||||
onMetaChange={this.handleMetaChange}
|
onMetaChange={this.handleMetaChange}
|
||||||
renderer={this.state.brew.renderer}
|
renderer={this.state.brew.renderer}
|
||||||
/>
|
/>
|
||||||
<BrewRenderer text={this.state.brew.text} style={this.state.brew.style} renderer={this.state.brew.renderer} theme={this.state.brew.theme} errors={this.state.htmlErrors}/>
|
<BrewRenderer text={this.state.brew.text} style={this.state.brew.style} renderer={this.state.brew.renderer} theme={this.state.brew.theme} lang={this.state.brew.lang} errors={this.state.htmlErrors}/>
|
||||||
</SplitPane>
|
</SplitPane>
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
|
|||||||
@@ -60,7 +60,8 @@ const PrintPage = createClass({
|
|||||||
|
|
||||||
renderStyle : function() {
|
renderStyle : function() {
|
||||||
if(!this.state.brew.style) return;
|
if(!this.state.brew.style) return;
|
||||||
return <div style={{ display: 'none' }} dangerouslySetInnerHTML={{ __html: `<style>@layer styleTab {\n${this.state.brew.style}\n} </style>` }} />;
|
//return <div style={{ display: 'none' }} dangerouslySetInnerHTML={{ __html: `<style>@layer styleTab {\n${this.state.brew.style}\n} </style>` }} />;
|
||||||
|
return <div style={{ display: 'none' }} dangerouslySetInnerHTML={{ __html: `<style>\n${this.state.brew.style}\n</style>` }} />;
|
||||||
},
|
},
|
||||||
|
|
||||||
renderPages : function(){
|
renderPages : function(){
|
||||||
|
|||||||
1
client/icons/Davek.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 791.04 953.29"><title>Davek</title><g id="Layer_2" data-name="Layer 2"><g id="Davek"><path d="M178.41,13.46a19.33,19.33,0,0,0-4.71,5.38q8.07,6.07,13.46,6.07a8.27,8.27,0,0,0,4.71-1.35,130.23,130.23,0,0,0,16.83-7.07,74.55,74.55,0,0,1,18.85-6.39h2.7q8.07,0,14.81,8.74a944.19,944.19,0,0,0,95.6,4.72q19.5,0,38.37-.67,69.33-2,139.68-5.72t139.7-5.06q16.82-.64,34.34-.66,50.49,0,98.29,3.36-17.5,12.12-22.55,31.64t-5,33.66q.64,22.89.66,45.1,0,47.13-3.36,97-6.07,74.05-9.78,148.11t-5,146.09v17.51a766.1,766.1,0,0,0,8.75,118.48,38.57,38.57,0,0,0-4,17.51,30.94,30.94,0,0,0,.67,6.06q2,12.12,3.36,23.22c.9,7.42,1.57,14.92,2,22.55v3.37a57.93,57.93,0,0,1-3.36,19.52c.43,4.5.67,8.77.67,12.8a260.65,260.65,0,0,1-2.7,37,344.26,344.26,0,0,0-4,52.52,133.5,133.5,0,0,0,8.09,45.44q8.07,22.57,33,36.68-6.06,8.78-20.19,8.77H762.1c-4.5-.45-8.53-.69-12.12-.69a78.11,78.11,0,0,0-21.54,2.7,579.1,579.1,0,0,0-63.64,3.71q-33.31,3.71-67.65,6.39t-68.66,3.37h-4a188.05,188.05,0,0,1-59.92-9.43q20.19-4,39.06-23.22t20.19-47.46q11.44-22.21,11.45-49.82a320.44,320.44,0,0,1,3.36-49.15q-9.45-4.69-10.09-8.75v-2.7a73,73,0,0,1,.66-8.74,105.81,105.81,0,0,0,3.37-12.8,7.49,7.49,0,0,0,.68-3.37q0-4.7-4.05-10.09c.45-4.93.69-10.1.69-15.48a311.71,311.71,0,0,0-3.37-46.45,207.31,207.31,0,0,1-1.35-24.25,274.58,274.58,0,0,1,4-45.1l15.5,6.73q-3.37-17.49-3.37-41.07,0-24.89,8.75-44.44a27.73,27.73,0,0,0,2-9.43,15.32,15.32,0,0,0-3.36-10.09,60.75,60.75,0,0,1-10.1-15.48l-7.39,6.73q2.67-47.79,8.74-99,3.35-33.63,3.37-65.29,0-14.81-.69-29a205.09,205.09,0,0,1-4-41.74,190.26,190.26,0,0,1,2-26.92q4-37,14.81-67.33a25.14,25.14,0,0,1-2.68-11.43,31.13,31.13,0,0,1,.66-6.07V140q0-6.72-8.74-10.09-3.37-16.83-5.73-31.3T521.07,77.41q-55.2,2.7-115.78,4.71-19.55.7-39.72.69-38.38,0-74.06-2.7c-5.4,4.5-8.08,9.21-8.08,14.14v1.34a41.5,41.5,0,0,0,4.37,15.49q3.7,7.4,7.4,15.16a35,35,0,0,1,3.71,15.13q32.31,34.35,64,68.68a335.89,335.89,0,0,1,51.83,73.38q13.46,7.4,18.51,17.49t10.11,19.87q5.06,9.78,10.1,18.85t16.5,11.78v12.12a194.5,194.5,0,0,1-37.38-4q-20.52-4-40.73-6.73a114.48,114.48,0,0,0-17.49-1.35,97.2,97.2,0,0,0-20.2,2q-17.52,4.05-31,20.19-16.84-1.35-27.27-9.75a76.13,76.13,0,0,1-17.51-20.2q-7.06-11.76-14.47-24.9a79.77,79.77,0,0,0-18.84-22.57A305.87,305.87,0,0,1,177.73,237q-28.29-33.67-54.54-69T68,99.31A381.16,381.16,0,0,0,0,38.37q12.79,0,22.89-9.75A190.69,190.69,0,0,1,44.76,10.44Q56.54,2,68.66,0H72Q82.8,0,97,10.76Z"/></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 2.4 KiB |
1
client/icons/Iokharic.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 428.05 941.17"><title>Iokharic</title><g id="Layer_2" data-name="Layer 2"><g id="Iokharic"><path d="M334.76,909.61V259.3l2.74-89.18c3.43,0,6.18-8.23,7.55-24.69,3.43,0,7.55-8.92,13.72-27.44,13-11,19.89-21.27,19.89-31.56,0-13-5.48-20.58-17.15-23.32l-30.87,2.74H320.36c-21.27,13-39.79,22.64-56.94,27.44h-37c-11.67,0-26.76,7.55-46,22q-12.34,0-30.86,16.46c-10.29,0-40.48,26.75-91.93,80.95,0,8.23-6.17,21.26-18.52,38.41l-3.43,15.78v41.84L67.23,343c2.74,0,9.6,6.86,19.89,19.9,24,18.52,36.36,30.86,36.36,38.41l-12.35,10.29H105c-24.7-15.78-45.28-32.93-62.43-52.13L15.78,316.92,0,266.85c3.43-17.84,7.55-29.5,13.72-35v-11c0-18.52,7.55-39.79,22-63.8,0-9.6,8.23-21.27,24.7-34.3,0-9.6,15.77-26.07,46.64-50.08,19.9-16.46,46-28.12,76.83-35,5.49-6.86,21.27-14.41,46.65-21.95C238,5.49,251.07,0,270.28,0h137.2c8.91,0,15.77,8.23,20.57,24V40.47l-5.48,8.23V166c0,17.15-7.55,31.55-21.95,43.22v41.15l-2.75,24.7q0,9.26,24.7,30.87v38.41c0,10.29-4.81,19.9-15.09,28.82h-6.86V558.39c0,55.57-4.81,97.41-15.1,124.16-4.8,2.75-7.54,19.21-9.6,48.71l2.74,17.15-2.74,76.14v30.19q0,32.93-32.93,86.43C337.5,937.74,334.76,926.76,334.76,909.61Z"/></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
1
client/icons/Rellanic.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 527.7 940.25"><title>Rellanic</title><g id="Layer_2" data-name="Layer 2"><g id="Rellanic"><path d="M527.7,5.45q-3.83,19.65-15,30.56a129.61,129.61,0,0,1-26.46,19.64q-9.84,6.56-31.66,15.28-19.63,7.65-31.64,16.38Q380.33,103.69,342.16,108a468.46,468.46,0,0,1-54,3.28q-15.83,0-30.56-1.1a53.19,53.19,0,0,0-20.19-6.55H217.74q-7.12,1.11-21.29,1.1a51.67,51.67,0,0,1-20.18-4.36q8.72,19.65,25.63,29.46,14.19,8.74,28.38,29.47a634.05,634.05,0,0,1,98.78,90.58l91.12,103.69a65.1,65.1,0,0,0-.54,8.19,42.47,42.47,0,0,0,.54,7.09c.73,1.82,1.27,3.29,1.64,4.37q7.08,8.75,10.92,12,1.62,1.1,12.55,14.19a14,14,0,0,1,3.27,6.55,9.75,9.75,0,0,1,1.1,4.37,9.62,9.62,0,0,1-1.1,4.36q35.46,43.66,51.3,89.5,3.25,9.82,5.45,19.64a288.59,288.59,0,0,1,10.37,68.75v8.19a296,296,0,0,1-9.81,76.94q-7.12,27.3-24,77.5L418,831.65Q383,872,344.88,899.31a243.27,243.27,0,0,1-90.59,38.19,179.84,179.84,0,0,1-31.64,2.75q-38.78,0-81.87-15.84A293.78,293.78,0,0,1,78,886.22a312.61,312.61,0,0,1-51.85-48,300.52,300.52,0,0,0-18-46.94,60.18,60.18,0,0,1-4.92-13.64,82.36,82.36,0,0,1-2.19-19.11,104.89,104.89,0,0,1,.56-10.91,176.12,176.12,0,0,1-1.64-24,199.79,199.79,0,0,1,2.72-32.74Q5.45,663,5.45,645a103.71,103.71,0,0,0-.54-10.92,242.44,242.44,0,0,1,50.74-67.66,646.83,646.83,0,0,0,57.86-61.12q11.44-10.89,25.09-13.1A88.3,88.3,0,0,1,163.71,489q14.17-1.11,29.46-1.1a108.11,108.11,0,0,0,28.38-7.63q17.44,8.75,27.29,12a124.47,124.47,0,0,1,28.38,13.1q8.71,4.38,23.46,17.46,9.29,9.86,17.47,28.38,7.07,12,9.27,21.83a35.16,35.16,0,0,1,1.64,9.83V585a80.23,80.23,0,0,1-8.73,27.28q-8.2,14.19-18,22.93a166.18,166.18,0,0,1-19.65,19.64q-13.1,8.74-20.72,13.1l-7.65-4.37v-1.64q0-12,6.55-18-8.17-6.55-10.36-10.92l-2.18-8.73c0-2.18-.74-5.81-2.19-10.91v-3.29a38,38,0,0,0-3.82-7.63,196.53,196.53,0,0,0-33.84-40.39Q185.53,542.43,162.61,537a163.71,163.71,0,0,0-50.75,9.81q-25.08,8.76-32.2,36Q67.12,615.56,67.13,654.3a256,256,0,0,0,3.26,39.83,176.75,176.75,0,0,0,5.47,28.38Q88.37,770,122.78,812a452.22,452.22,0,0,0,103.13,58.94,153.57,153.57,0,0,0,107,5.45q25.63-12,37.66-27.28,13.62-14.21,23.46-34.93,10.36-18.57,20.2-39.29Q426.72,753.05,437.1,740q3.27-44.76,5.47-61.12a228.17,228.17,0,0,0,3.26-38.21,213.15,213.15,0,0,0-1.64-26.19,245.3,245.3,0,0,0-8.17-48q-2.2-8.17-4.93-16.36-9.27-30.55-34.92-61.12a70,70,0,0,0-2.18-18,29.12,29.12,0,0,0-4.37-10.37,175.28,175.28,0,0,0-17.46-29.48l-18.55-27.27q-12-16.38-16.38-28.38a282.35,282.35,0,0,1-27.81-28.37q-20.22-26.2-24-31.66Q269,295.76,260.29,286q-10.92-12-31.1-25.11-36.56-31.65-79.12-70.94-45.31-39.28-88.41-66.58-14.74-8.17-17.46-16.9a16.93,16.93,0,0,0-.54-3.83V99.87q0-8.73,6.54-19.11A102.47,102.47,0,0,1,63.3,61.12q9.27-9.82,12.56-18.56a223.6,223.6,0,0,1,38.73-3.27,271,271,0,0,1,40.93,3.27A367.15,367.15,0,0,0,215,47.48c6.91,0,13.64-.17,20.2-.56a45,45,0,0,0,21.27,5.47q17.44,0,25.65-1.1h22.93a77.75,77.75,0,0,1,24,7.65,114,114,0,0,1,27.82-3.29H364q27.25,2.2,39.29,2.19,16.34,0,36.55-5.45,19.1-6.55,27.83-22.93h2.72A20.48,20.48,0,0,0,484.58,24c2.17-4.71,6.17-7.09,12-7.09a26.6,26.6,0,0,1,4.92.54v-.54c0-1.08.72-3.46,2.19-7.11a36.74,36.74,0,0,1,6-6.54C512.57,1.1,515.12,0,517.32,0,521,0,524.41,1.82,527.7,5.45Z"/></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 3.1 KiB |
48
client/icons/book-front-cover.svg
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 541.53217 512"
|
||||||
|
version="1.1"
|
||||||
|
id="svg22127"
|
||||||
|
sodipodi:docname="book-front-cover.svg"
|
||||||
|
width="541.53217"
|
||||||
|
height="512"
|
||||||
|
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs22131" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview22129"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#111111"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:showpageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="1"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="0.39257813"
|
||||||
|
inkscape:cx="-263.64179"
|
||||||
|
inkscape:cy="444.49751"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="991"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg22127" />
|
||||||
|
<!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
|
||||||
|
<g
|
||||||
|
id="g20308"
|
||||||
|
transform="matrix(3.7795276,0,0,3.7795276,-201.76367,-251.58203)">
|
||||||
|
<path
|
||||||
|
id="rect20232"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:17.9;stroke-linejoin:bevel;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke markers fill;stop-color:#000000"
|
||||||
|
d="m 78.783305,66.564412 c -14.022889,0 -25.4,11.377111 -25.4,25.4 v 84.666668 c 0,14.02289 11.377111,25.4 25.4,25.4 h 76.199995 8.46667 c 4.68312,0 8.46667,-3.78355 8.46667,-8.46667 0,-4.68311 -3.78355,-8.46666 -8.46667,-8.46666 v -16.93334 c 4.68312,0 8.46667,-3.78355 8.46667,-8.46666 v -1.9327 c -0.0322,-0.27545 -0.0652,-0.54693 -0.0946,-0.83923 -0.17511,-1.74441 -0.30542,-3.81626 -0.37672,-6.02909 -0.18285,-5.67612 -0.29322,-5.86808 -0.63459,-6.62698 -0.74838,-1.66366 -2.65792,-3.64941 -4.38681,-4.49844 -1.41973,-0.69716 -0.72585,-0.45434 -1.20923,-0.51934 -0.47548,-0.0639 -2.54581,-0.13856 -6.47454,-0.14056 -0.0907,2.9929 -0.0862,4.81682 -0.58601,7.244 -0.28023,1.36071 -0.97957,3.42078 -2.40812,5.10356 -1.42519,1.67884 -2.81498,2.35811 -3.28145,2.61896 -3.14428,1.76375 -5.09549,2.43427 -9.41597,1.33997 -2.05224,-0.5197 -2.32631,-0.92288 -2.76159,-1.19527 -0.43528,-0.27239 -0.71007,-0.47684 -0.97461,-0.67593 -0.52909,-0.39816 -0.97871,-0.77171 -1.48622,-1.20664 -1.015,-0.86987 -2.20927,-1.95397 -3.6096,-3.26182 -2.80065,-2.61568 -6.38094,-6.09226 -10.18335,-9.90844 -6.19117,-6.21357 -9.5466,-9.59164 -11.7874,-12.16412 -1.1204,-1.28623 -2.03413,-2.38181 -2.90576,-4.03127 -0.87162,-1.64948 -1.40664,-4.21493 -1.40664,-5.61103 0,-1.4012 0.54783,-3.99366 1.42989,-5.64668 0.88206,-1.65304 1.8039,-2.74855 2.94142,-4.04679 2.27504,-2.59646 5.70131,-6.03358 12.03699,-12.369267 7.37691,-7.376888 10.87768,-11.090687 14.75208,-13.810527 1.45289,-1.019939 3.46378,-2.249133 6.08386,-2.580204 0.87337,-0.110323 1.8133,-0.120299 2.82412,0.0098 4.0433,0.520471 6.12413,2.832857 7.01973,3.728454 1.29782,1.297845 3.1373,4.826955 3.46852,7.049182 0.29817,2.00025 0.26393,3.770666 0.25993,6.212541 0.57954,0.0034 0.50388,0.0217 1.17564,0.0217 4.54211,0 8.44363,0.111537 11.991,0.50953 v -21.41004 c 0,-4.683115 -3.78355,-8.466667 -8.46667,-8.466667 h -8.46667 z m 0,101.599998 h 67.733335 v 16.93334 H 78.783305 c -4.683115,0 -8.466667,-3.78357 -8.466667,-8.46667 0,-4.68313 3.783552,-8.46667 8.466667,-8.46667 z" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;fill:#000000;stroke-width:17.9;stroke-linejoin:round;-inkscape-stroke:none;paint-order:stroke markers fill"
|
||||||
|
d="m 186.69094,157.95633 c 2.67243,-2.24871 7.17957,-9.39389 8.63888,-13.69528 1.03796,-3.05942 1.31928,-5.13546 1.33362,-9.84167 0.0278,-9.1246 -2.25302,-14.5915 -8.79325,-21.07662 -6.8535,-6.79576 -12.35348,-8.46107 -27.94423,-8.46107 -8.05417,0 -9.45684,-0.12924 -9.75203,-0.89852 -0.18964,-0.49417 -0.34479,-3.81715 -0.34479,-7.384389 0,-5.728497 -0.13266,-6.618534 -1.13607,-7.621956 -2.57777,-2.57775 -3.29907,-2.07141 -18.02212,12.651595 -12.64444,12.64444 -13.78771,13.94921 -13.78771,15.73575 0,1.78396 1.13629,3.08846 13.49078,15.48766 7.47518,7.50224 14.10644,13.69554 14.8715,13.88928 0.78576,0.19902 2.0096,-0.002 2.84016,-0.46789 1.42969,-0.80092 1.46523,-0.97351 1.74346,-8.46583 l 0.28402,-7.64825 h 8.52049 c 8.16738,0 8.65373,0.0655 11.73586,1.579 3.72428,1.82893 6.9202,5.12058 8.60236,8.86006 0.94352,2.09748 1.22898,4.1112 1.41901,10.01012 0.13083,4.06143 0.49647,7.70394 0.81253,8.09446 0.94895,1.17251 3.64241,0.80611 5.48753,-0.74645 z"
|
||||||
|
id="path20297" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.6 KiB |
@@ -13,3 +13,36 @@
|
|||||||
.position-bottom-right {
|
.position-bottom-right {
|
||||||
content: url('../icons/position-bottom-right.svg');
|
content: url('../icons/position-bottom-right.svg');
|
||||||
}
|
}
|
||||||
|
.position-top {
|
||||||
|
content: url('../icons/position-top.svg');
|
||||||
|
}
|
||||||
|
.position-right {
|
||||||
|
content: url('../icons/position-right.svg');
|
||||||
|
}
|
||||||
|
.position-bottom {
|
||||||
|
content: url('../icons/position-bottom.svg');
|
||||||
|
}
|
||||||
|
.position-left {
|
||||||
|
content: url('../icons/position-left.svg');
|
||||||
|
}
|
||||||
|
.mask-edge {
|
||||||
|
content: url('../icons/mask-edge.svg');
|
||||||
|
}
|
||||||
|
.mask-corner {
|
||||||
|
content: url('../icons/mask-corner.svg');
|
||||||
|
}
|
||||||
|
.fa-file-c {
|
||||||
|
content: url('../icons/fa-file-c.svg');
|
||||||
|
}
|
||||||
|
.book-front-cover {
|
||||||
|
content: url('../icons/book-front-cover.svg');
|
||||||
|
}
|
||||||
|
.davek {
|
||||||
|
content: url('../icons/Davek.svg');
|
||||||
|
}
|
||||||
|
.rellanic {
|
||||||
|
content: url('../icons/Rellanic.svg');
|
||||||
|
}
|
||||||
|
.iokharic {
|
||||||
|
content: url('../icons/Iokharic.svg');
|
||||||
|
}
|
||||||
|
|||||||
30
client/icons/fa-file-c.svg
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 610.4 816.5" style="enable-background:new 0 0 610.4 816.5;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#FFFFFF;}
|
||||||
|
.st1{fill:#FFFFFF;stroke:#FFFFFF;stroke-width:20;stroke-miterlimit:10;}
|
||||||
|
</style>
|
||||||
|
<title>fa-file-c</title>
|
||||||
|
<g id="Layer_2_1_">
|
||||||
|
<g id="Layer_1-2">
|
||||||
|
<g id="page">
|
||||||
|
<path id="page-2" d="M610.3,468.3c0,77.3,0.2,154.5,0,231.8s-39.8,116.5-116.8,116.4c-127.6,0-255.1,0-382.7,0
|
||||||
|
c-68.1,0-110.5-41.7-110.6-109.8c-0.2-197.7-0.2-395.5,0-593.2c0-68.4,43.2-110.9,112.1-111c90-0.1,180,0.2,270-0.2
|
||||||
|
c12.8,0,21.5,0.6,32.9,4c17.1,5,152.7,150.7,190.7,188.8c-0.7,18-6,5.7,1.4,35.1c0,6.8,3.1,11.2,3.1,18.1
|
||||||
|
C610.2,320.8,610.3,395.7,610.3,468.3z"/>
|
||||||
|
<path id="white_corner" class="st0" d="M364.1,0v200c0,9.3,1.7,25.6,13.1,36.8c12,11.7,28.8,12.1,37.5,12.2
|
||||||
|
c119.8,1.3,195.6,0.4,195.6,0.4l0,0l-0.3-54.3l-197,1l3-192L364.1,0z"/>
|
||||||
|
</g>
|
||||||
|
<path class="st1" d="M317.7,719.8c-38.3,0-71-8.1-98.3-24.3c-27.2-16.2-48.1-39.2-62.7-69C142.3,596.8,135,561.2,135,520
|
||||||
|
c0-30.9,4.1-58.6,12.4-83.1c8.3-24.5,20.2-45.3,35.9-62.4c15.6-17.1,34.9-30.4,57.7-39.8s48.4-14.1,76.7-14.1
|
||||||
|
c22.1-0.1,44,3.1,65.1,9.7c20.6,6.4,38.4,15.9,53.5,28.4c4.8,3.7,8,7.8,9.7,12.4c1.6,4.2,1.8,8.9,0.6,13.2
|
||||||
|
c-1.2,4.1-3.5,7.7-6.6,10.5c-3.1,2.8-7.2,4.2-11.3,4.1c-4.4,0-9.4-1.8-14.9-5.5c-13-10.5-27.7-18.6-43.6-23.7
|
||||||
|
c-16.6-5.3-33.9-7.9-51.3-7.7c-29.1,0-53.7,6.2-74,18.5s-35.5,30.3-45.8,53.8c-10.3,23.6-15.4,52.1-15.4,85.5s5.1,62.1,15.4,85.9
|
||||||
|
c10.3,23.7,25.6,41.8,45.8,54.1c20.2,12.3,44.9,18.5,74,18.5c17.4,0.1,34.8-2.6,51.3-8c16.2-5.3,31.3-13.5,44.7-24
|
||||||
|
c5.5-3.7,10.5-5.4,14.9-5.3c4,0.1,7.9,1.5,11,4.1c3,2.7,5.2,6.1,6.4,9.9c1.3,4.1,1.3,8.6,0,12.7c-1.3,4.4-4.1,8.3-8.6,11.6
|
||||||
|
c-15.5,13.3-33.6,23.3-54.4,30.1C362.7,716.6,340.3,720,317.7,719.8z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
63
client/icons/mask-corner.svg
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 448 512"
|
||||||
|
version="1.1"
|
||||||
|
id="svg135"
|
||||||
|
sodipodi:docname="mask-corner.svg"
|
||||||
|
width="448"
|
||||||
|
height="512"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs139"><pattern
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#Strips1_1"
|
||||||
|
id="pattern3077"
|
||||||
|
patternTransform="matrix(23.131931,-23.131931,19.25517,19.25517,26.214281,-26.952711)" /><pattern
|
||||||
|
inkscape:collect="always"
|
||||||
|
patternUnits="userSpaceOnUse"
|
||||||
|
width="2"
|
||||||
|
height="1"
|
||||||
|
patternTransform="translate(0,0) scale(10,10)"
|
||||||
|
id="Strips1_1"
|
||||||
|
inkscape:stockid="Stripes 1:1"><rect
|
||||||
|
style="fill:black;stroke:none"
|
||||||
|
x="0"
|
||||||
|
y="-0.5"
|
||||||
|
width="1"
|
||||||
|
height="2"
|
||||||
|
id="rect2097" /></pattern></defs><sodipodi:namedview
|
||||||
|
id="namedview137"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
showgrid="false"
|
||||||
|
showguides="false"
|
||||||
|
inkscape:zoom="0.95758074"
|
||||||
|
inkscape:cx="275.17262"
|
||||||
|
inkscape:cy="306.50157"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="991"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg135" /><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path
|
||||||
|
id="rect12201"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
|
||||||
|
d="M 48,-5.2e-6 C 21.40803,-5.2e-6 1.98e-5,21.408025 1.98e-5,47.999995 V 464 C 1.98e-5,490.59197 21.40803,512 48,512 h 352 c 26.59198,0 48,-21.40803 48,-48 V 47.999995 C 448,21.408025 426.59198,-5.2e-6 400,-5.2e-6 Z M 64,63.999995 H 384 V 448 H 64 Z" /><rect
|
||||||
|
style="fill:url(#pattern3077);fill-opacity:1;stroke:#000000;stroke-width:48;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
|
||||||
|
id="rect12206"
|
||||||
|
width="208"
|
||||||
|
height="240"
|
||||||
|
x="32.000011"
|
||||||
|
y="32.000011"
|
||||||
|
rx="48"
|
||||||
|
ry="48" /></svg>
|
||||||
|
After Width: | Height: | Size: 2.6 KiB |
69
client/icons/mask-edge.svg
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 448 512"
|
||||||
|
version="1.1"
|
||||||
|
id="svg135"
|
||||||
|
sodipodi:docname="mask-edge.svg"
|
||||||
|
width="448"
|
||||||
|
height="512"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs139"><pattern
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#Strips1_1"
|
||||||
|
id="pattern3077"
|
||||||
|
patternTransform="matrix(23.131931,-23.13193,19.25517,19.25517,26.214281,-26.952711)" /><pattern
|
||||||
|
inkscape:collect="always"
|
||||||
|
patternUnits="userSpaceOnUse"
|
||||||
|
width="2"
|
||||||
|
height="1"
|
||||||
|
patternTransform="translate(0,0) scale(10,10)"
|
||||||
|
id="Strips1_1"
|
||||||
|
inkscape:stockid="Stripes 1:1"><rect
|
||||||
|
style="fill:black;stroke:none"
|
||||||
|
x="0"
|
||||||
|
y="-0.5"
|
||||||
|
width="1"
|
||||||
|
height="2"
|
||||||
|
id="rect2097" /></pattern></defs><sodipodi:namedview
|
||||||
|
id="namedview137"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
showgrid="false"
|
||||||
|
showguides="false"
|
||||||
|
inkscape:zoom="0.95758074"
|
||||||
|
inkscape:cx="231.31209"
|
||||||
|
inkscape:cy="171.78708"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="991"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg135" /><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path
|
||||||
|
id="rect12201"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
|
||||||
|
d="M 48,-5.2e-6 C 21.40803,-5.2e-6 1.98e-5,21.408025 1.98e-5,47.999995 V 464 C 1.98e-5,490.59197 21.40803,512 48,512 h 352 c 26.59198,0 48,-21.40803 48,-48 V 47.999995 C 448,21.408025 426.59198,-5.2e-6 400,-5.2e-6 Z M 64,63.999995 H 384 V 448 H 64 Z" /><rect
|
||||||
|
style="fill:url(#pattern3077);fill-opacity:1;stroke:#000000;stroke-width:48;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
|
||||||
|
id="rect12206"
|
||||||
|
width="208"
|
||||||
|
height="447.99997"
|
||||||
|
x="32.000011"
|
||||||
|
y="32.000011"
|
||||||
|
rx="48"
|
||||||
|
ry="48" /><rect
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke-width:47.9999;stroke-linejoin:round;stroke-dasharray:none;paint-order:fill markers stroke;stop-color:#000000"
|
||||||
|
id="rect4640"
|
||||||
|
width="48"
|
||||||
|
height="512"
|
||||||
|
x="216"
|
||||||
|
y="0" /></svg>
|
||||||
|
After Width: | Height: | Size: 2.9 KiB |
@@ -1 +1,46 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 495 495"><path fill-opacity=".995" d="M495 135.49V0H359.51v135.49M482.72 11.37v113.26H371.9V11.37zM135.49 315.245v-135.49H0v135.49m123.21-124.12v113.26H12.39v-113.26zm12.28-55.635V0H0v135.49M123.21 11.37v113.26H12.39V11.37zm192.035 124.12V0h-135.49v135.49m123.21-124.12v113.26h-110.82V11.37zm12.28 303.875v-135.49h-135.49v135.49m123.21-124.12v113.26h-110.82v-113.26zM495 315.245v-135.49H359.51v135.49m123.21-124.12v113.26H371.9v-113.26zM135.49 495V359.51H0V495Zm179.755 0V359.51h-135.49V495m123.21-124.12v113.26h-110.82V370.88zM495 495V359.51H359.51V495m123.21-124.12v113.26H371.9V370.88z"/></svg>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 448 512"
|
||||||
|
version="1.1"
|
||||||
|
id="svg135"
|
||||||
|
sodipodi:docname="position-bottom-left.svg"
|
||||||
|
width="448"
|
||||||
|
height="512"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs139" /><sodipodi:namedview
|
||||||
|
id="namedview137"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
showgrid="false"
|
||||||
|
showguides="false"
|
||||||
|
inkscape:zoom="0.70792086"
|
||||||
|
inkscape:cx="174.45453"
|
||||||
|
inkscape:cy="325.60137"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="991"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg135" /><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path
|
||||||
|
id="rect12201"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
|
||||||
|
d="m 48,511.99998 c -26.59197,0 -48.00000035682677,-21.40803 -48.00000035682677,-48 v -416 C -3.5682677e-7,21.40801 21.40803,-1.9692461e-5 48,-1.9692461e-5 h 352 c 26.59198,0 48,21.408029692461 48,47.999999692461 v 416 c 0,26.59197 -21.40802,48 -48,48 z m 16,-64 h 320 v -384 H 64 Z" /><rect
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
|
||||||
|
id="rect12206"
|
||||||
|
width="208"
|
||||||
|
height="240"
|
||||||
|
x="-3.5682677e-07"
|
||||||
|
y="-512"
|
||||||
|
rx="48"
|
||||||
|
ry="48"
|
||||||
|
transform="scale(1,-1)" /></svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 650 B After Width: | Height: | Size: 2.1 KiB |
@@ -1 +1,46 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 495 495"><g fill-opacity=".995"><path d="M135.49 0H0v135.49h135.49M11.37 12.28h113.26V123.1H11.37zM315.245 359.51h-135.49V495h135.49m-124.12-123.21h113.26v110.82h-113.26zM135.49 359.51H0V495h135.49M11.37 371.79h113.26v110.82H11.37zM135.49 179.755H0v135.49h135.49M11.37 192.035h113.26v110.82H11.37zM315.245 179.755h-135.49v135.49h135.49m-124.12-123.21h113.26v110.82h-113.26zM315.245 0h-135.49v135.49h135.49M191.125 12.28h113.26V123.1h-113.26zM495 359.51H359.51V495H495ZM495 179.755H359.51v135.49H495m-124.12-123.21h113.26v110.82H370.88zM495 0H359.51v135.49H495M370.88 12.28h113.26V123.1H370.88z"/></g></svg>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 448 512"
|
||||||
|
version="1.1"
|
||||||
|
id="svg135"
|
||||||
|
sodipodi:docname="position-bottom-right.svg"
|
||||||
|
width="448"
|
||||||
|
height="512"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs139" /><sodipodi:namedview
|
||||||
|
id="namedview137"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
showgrid="false"
|
||||||
|
showguides="false"
|
||||||
|
inkscape:zoom="0.70792086"
|
||||||
|
inkscape:cx="174.45453"
|
||||||
|
inkscape:cy="325.60137"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="991"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg135" /><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path
|
||||||
|
id="rect12201"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
|
||||||
|
d="m 400,511.99998 c 26.59197,0 48,-21.40803 48,-48 v -416 C 448,21.40801 426.59197,-1.9692461e-5 400,-1.9692461e-5 H 48 C 21.40802,-1.9692461e-5 -3.5682677e-7,21.40801 -3.5682677e-7,47.99998 v 416 c 0,26.59197 21.40802035682677,48 48.00000035682677,48 z m -16,-64 H 64 v -384 h 320 z" /><rect
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
|
||||||
|
id="rect12206"
|
||||||
|
width="208"
|
||||||
|
height="240"
|
||||||
|
x="-448"
|
||||||
|
y="-512"
|
||||||
|
rx="48"
|
||||||
|
ry="48"
|
||||||
|
transform="scale(-1)" /></svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 659 B After Width: | Height: | Size: 2.1 KiB |
46
client/icons/position-bottom.svg
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 448 512"
|
||||||
|
version="1.1"
|
||||||
|
id="svg135"
|
||||||
|
sodipodi:docname="position-bottom.svg"
|
||||||
|
width="448"
|
||||||
|
height="512"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs139" /><sodipodi:namedview
|
||||||
|
id="namedview137"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
showgrid="false"
|
||||||
|
showguides="false"
|
||||||
|
inkscape:zoom="1.0011513"
|
||||||
|
inkscape:cx="273.18549"
|
||||||
|
inkscape:cy="216.25103"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="991"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg135" /><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path
|
||||||
|
id="rect12201-2"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
|
||||||
|
d="m 48,512.00004 c -26.5919,0 -48,-21.4081 -48,-48 V 47.999996 C 0,21.408026 21.4081,-3.8146973e-6 48,-3.8146973e-6 h 352 c 26.592,0 48,21.4080298146973 48,47.9999998146973 V 464.00004 c 0,26.5919 -21.408,48 -48,48 z m 16,-64 H 384 V 63.999996 H 64 Z" /><rect
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30.0001;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
|
||||||
|
id="rect12206-8"
|
||||||
|
width="447.99997"
|
||||||
|
height="240"
|
||||||
|
x="1.40625e-05"
|
||||||
|
y="-512.00006"
|
||||||
|
rx="48"
|
||||||
|
ry="48"
|
||||||
|
transform="scale(1,-1)" /></svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
45
client/icons/position-left.svg
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 448 512"
|
||||||
|
version="1.1"
|
||||||
|
id="svg135"
|
||||||
|
sodipodi:docname="position-left.svg"
|
||||||
|
width="448"
|
||||||
|
height="512"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs139" /><sodipodi:namedview
|
||||||
|
id="namedview137"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
showgrid="false"
|
||||||
|
showguides="false"
|
||||||
|
inkscape:zoom="0.70792086"
|
||||||
|
inkscape:cx="164.56642"
|
||||||
|
inkscape:cy="243.6713"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="991"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg135" /><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path
|
||||||
|
id="rect12201-0"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
|
||||||
|
d="M 48,0 C 21.4081,0 0,21.40803 0,48 v 416 c 0,26.59197 21.4081,48 48,48 h 352.0001 c 26.5919,0 48,-21.40803 48,-48 V 48 c 0,-26.59197 -21.4081,-48 -48,-48 z M 64,64 H 384.0001 V 448 H 64 Z" /><rect
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
|
||||||
|
id="rect12206-2"
|
||||||
|
width="208"
|
||||||
|
height="512.00006"
|
||||||
|
x="7.0762391e-05"
|
||||||
|
y="-8.8710935e-05"
|
||||||
|
rx="48"
|
||||||
|
ry="48.000004" /></svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
46
client/icons/position-right.svg
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 448 512"
|
||||||
|
version="1.1"
|
||||||
|
id="svg135"
|
||||||
|
sodipodi:docname="position-right.svg"
|
||||||
|
width="448"
|
||||||
|
height="512"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs139" /><sodipodi:namedview
|
||||||
|
id="namedview137"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
showgrid="false"
|
||||||
|
showguides="false"
|
||||||
|
inkscape:zoom="0.70792086"
|
||||||
|
inkscape:cx="164.56642"
|
||||||
|
inkscape:cy="243.6713"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="991"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg135" /><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path
|
||||||
|
id="rect12201-0"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
|
||||||
|
d="m 400.0001,0 c 26.5919,0 48,21.40803 48,48 v 416 c 0,26.59197 -21.4081,48 -48,48 H 48 C 21.4081,512 0,490.59197 0,464 V 48 C 0,21.40803 21.4081,0 48,0 Z m -16,64 H 64 v 384 h 320.0001 z" /><rect
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
|
||||||
|
id="rect12206-2"
|
||||||
|
width="208"
|
||||||
|
height="512.00006"
|
||||||
|
x="-448.00003"
|
||||||
|
y="-8.8710935e-05"
|
||||||
|
rx="48"
|
||||||
|
ry="48.000004"
|
||||||
|
transform="scale(-1,1)" /></svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -1 +1,45 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 495 495"><path fill-opacity=".995" d="M359.51 495H495V359.51H359.51m124.12 123.21H370.37V371.9h113.26zM179.755 135.49h135.49V0h-135.49m124.12 123.21h-113.26V12.39h113.26zM359.51 135.49H495V0H359.51m124.12 123.21H370.37V12.39h113.26zM359.51 315.245H495v-135.49H359.51m124.12 123.21H370.37v-110.82h113.26zM179.755 315.245h135.49v-135.49h-135.49m124.12 123.21h-113.26v-110.82h113.26zM179.755 495h135.49V359.51h-135.49m124.12 123.21h-113.26V371.9h113.26zM0 135.49h135.49V0H0ZM0 315.245h135.49v-135.49H0m124.12 123.21H10.86v-110.82h113.26zM0 495h135.49V359.51H0m124.12 123.21H10.86V371.9h113.26z"/></svg>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 448 512"
|
||||||
|
version="1.1"
|
||||||
|
id="svg135"
|
||||||
|
sodipodi:docname="position-top-left.svg"
|
||||||
|
width="448"
|
||||||
|
height="512"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs139" /><sodipodi:namedview
|
||||||
|
id="namedview137"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
showgrid="false"
|
||||||
|
showguides="false"
|
||||||
|
inkscape:zoom="0.70792086"
|
||||||
|
inkscape:cx="174.45453"
|
||||||
|
inkscape:cy="325.60137"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="991"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg135" /><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path
|
||||||
|
id="rect12201"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
|
||||||
|
d="M 48,0 C 21.40803,0 0,21.40803 0,48 v 416 c 0,26.59197 21.40803,48 48,48 h 352 c 26.59198,0 48,-21.40803 48,-48 V 48 C 448,21.40803 426.59198,0 400,0 Z M 64,64 H 384 V 448 H 64 Z" /><rect
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
|
||||||
|
id="rect12206"
|
||||||
|
width="208"
|
||||||
|
height="240"
|
||||||
|
x="-3.5682677e-07"
|
||||||
|
y="-1.9692461e-05"
|
||||||
|
rx="48"
|
||||||
|
ry="48" /></svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 652 B After Width: | Height: | Size: 1.9 KiB |
@@ -1 +1,46 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 495 495"><g fill-opacity=".995"><path d="M0 359.51V495h135.49V359.51M12.28 483.63V370.37H123.1v113.26zM359.51 179.755v135.49H495v-135.49m-123.21 124.12v-113.26h110.82v113.26zM359.51 359.51V495H495V359.51M371.79 483.63V370.37h110.82v113.26zM179.755 359.51V495h135.49V359.51m-123.21 124.12V370.37h110.82v113.26zM179.755 179.755v135.49h135.49v-135.49m-123.21 124.12v-113.26h110.82v113.26zM0 179.755v135.49h135.49v-135.49M12.28 303.875v-113.26H123.1v113.26zM359.51 0v135.49H495V0ZM179.755 0v135.49h135.49V0m-123.21 124.12V10.86h110.82v113.26zM0 0v135.49h135.49V0M12.28 124.12V10.86H123.1v113.26z"/></g></svg>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 448 512"
|
||||||
|
version="1.1"
|
||||||
|
id="svg135"
|
||||||
|
sodipodi:docname="position-top-right.svg"
|
||||||
|
width="448"
|
||||||
|
height="512"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs139" /><sodipodi:namedview
|
||||||
|
id="namedview137"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
showgrid="false"
|
||||||
|
showguides="false"
|
||||||
|
inkscape:zoom="0.70792086"
|
||||||
|
inkscape:cx="174.45453"
|
||||||
|
inkscape:cy="325.60137"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="991"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg135" /><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path
|
||||||
|
id="rect12201"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
|
||||||
|
d="m 400,0 c 26.59197,0 48,21.40803 48,48 v 416 c 0,26.59197 -21.40803,48 -48,48 H 48 C 21.40802,512 -3.5682677e-7,490.59197 -3.5682677e-7,464 V 48 C -3.5682677e-7,21.40803 21.40802,0 48,0 Z M 384,64 H 64 v 384 h 320 z" /><rect
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
|
||||||
|
id="rect12206"
|
||||||
|
width="208"
|
||||||
|
height="240"
|
||||||
|
x="-448"
|
||||||
|
y="-1.9692461e-05"
|
||||||
|
rx="48"
|
||||||
|
ry="48"
|
||||||
|
transform="scale(-1,1)" /></svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 657 B After Width: | Height: | Size: 2.0 KiB |
45
client/icons/position-top.svg
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 448 512"
|
||||||
|
version="1.1"
|
||||||
|
id="svg135"
|
||||||
|
sodipodi:docname="position-top.svg"
|
||||||
|
width="448"
|
||||||
|
height="512"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs139" /><sodipodi:namedview
|
||||||
|
id="namedview137"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
showgrid="false"
|
||||||
|
showguides="false"
|
||||||
|
inkscape:zoom="1.0011513"
|
||||||
|
inkscape:cx="273.18549"
|
||||||
|
inkscape:cy="216.25103"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="991"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg135" /><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path
|
||||||
|
id="rect12201-2"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
|
||||||
|
d="M 48,0 C 21.4081,0 0,21.4081 0,48 v 416.00004 c 0,26.59197 21.4081,48 48,48 h 352 c 26.592,0 48,-21.40803 48,-48 V 48 C 448,21.4081 426.592,0 400,0 Z M 64,64 H 384 V 448.00004 H 64 Z" /><rect
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30.0001;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
|
||||||
|
id="rect12206-8"
|
||||||
|
width="447.99997"
|
||||||
|
height="240"
|
||||||
|
x="1.40625e-05"
|
||||||
|
y="-3.8146973e-06"
|
||||||
|
rx="48"
|
||||||
|
ry="48" /></svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
18055
package-lock.json
generated
40
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "homebrewery",
|
"name": "homebrewery",
|
||||||
"description": "Create authentic looking D&D homebrews using only markdown",
|
"description": "Create authentic looking D&D homebrews using only markdown",
|
||||||
"version": "3.6.0",
|
"version": "3.7.2",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "16.11.x"
|
"node": "16.11.x"
|
||||||
},
|
},
|
||||||
@@ -12,23 +12,22 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "node scripts/dev.js",
|
"dev": "node scripts/dev.js",
|
||||||
"quick": "node scripts/quick.js",
|
"quick": "node scripts/quick.js",
|
||||||
"build": "node scripts/buildHomebrew.js",
|
"build": "node scripts/buildHomebrew.js && node scripts/buildAdmin.js",
|
||||||
"buildall": "node scripts/buildHomebrew.js && node scripts/buildAdmin.js",
|
|
||||||
"builddev": "node scripts/buildHomebrew.js --dev",
|
"builddev": "node scripts/buildHomebrew.js --dev",
|
||||||
"lint": "eslint --fix **/*.{js,jsx}",
|
"lint": "eslint --fix **/*.{js,jsx}",
|
||||||
"lint:dry": "eslint **/*.{js,jsx}",
|
"lint:dry": "eslint **/*.{js,jsx}",
|
||||||
"circleci": "npm test && eslint **/*.{js,jsx} --max-warnings=0",
|
"circleci": "npm test && eslint **/*.{js,jsx} --max-warnings=0",
|
||||||
"verify": "npm run lint && npm test",
|
"verify": "npm run lint && npm test",
|
||||||
"test": "jest",
|
"test": "jest --runInBand",
|
||||||
"test:api-unit": "jest server/*.spec.js --verbose",
|
"test:api-unit": "jest server/*.spec.js --verbose",
|
||||||
"test:coverage": "jest --coverage --silent",
|
"test:coverage": "jest --coverage --silent --runInBand",
|
||||||
"test:dev": "jest --verbose --watch",
|
"test:dev": "jest --verbose --watch",
|
||||||
"test:basic": "jest tests/markdown/basic.test.js --verbose",
|
"test:basic": "jest tests/markdown/basic.test.js --verbose",
|
||||||
"test:mustache-span": "jest tests/markdown/mustache-span.test.js --verbose",
|
"test:mustache-span": "jest tests/markdown/mustache-span.test.js --verbose",
|
||||||
"test:route": "jest tests/routes/static-pages.test.js --verbose",
|
"test:route": "jest tests/routes/static-pages.test.js --verbose",
|
||||||
"phb": "node scripts/phb.js",
|
"phb": "node scripts/phb.js",
|
||||||
"prod": "set NODE_ENV=production && npm run build",
|
"prod": "set NODE_ENV=production && npm run build",
|
||||||
"postinstall": "npm run buildall",
|
"postinstall": "npm run build",
|
||||||
"start": "node server.js"
|
"start": "node server.js"
|
||||||
},
|
},
|
||||||
"author": "stolksdorf",
|
"author": "stolksdorf",
|
||||||
@@ -37,12 +36,15 @@
|
|||||||
"build/*"
|
"build/*"
|
||||||
],
|
],
|
||||||
"jest": {
|
"jest": {
|
||||||
"testTimeout": 15000,
|
"testTimeout": 30000,
|
||||||
"modulePaths": [
|
"modulePaths": [
|
||||||
"mode_modules",
|
"node_modules",
|
||||||
"shared",
|
"shared",
|
||||||
"server"
|
"server"
|
||||||
],
|
],
|
||||||
|
"coveragePathIgnorePatterns": [
|
||||||
|
"build/*"
|
||||||
|
],
|
||||||
"coverageThreshold" : {
|
"coverageThreshold" : {
|
||||||
"global" : {
|
"global" : {
|
||||||
"statements" : 25,
|
"statements" : 25,
|
||||||
@@ -68,11 +70,12 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "^7.20.12",
|
"@babel/core": "^7.21.3",
|
||||||
"@babel/plugin-transform-runtime": "^7.19.6",
|
"@babel/plugin-transform-runtime": "^7.21.0",
|
||||||
"@babel/preset-env": "^7.19.4",
|
"@babel/preset-env": "^7.19.4",
|
||||||
"@babel/preset-react": "^7.18.6",
|
"@babel/preset-react": "^7.18.6",
|
||||||
"body-parser": "^1.20.1",
|
"@googleapis/drive": "^5.0.1",
|
||||||
|
"body-parser": "^1.20.2",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
"codemirror": "^5.65.6",
|
"codemirror": "^5.65.6",
|
||||||
"cookie-parser": "^1.4.6",
|
"cookie-parser": "^1.4.6",
|
||||||
@@ -81,32 +84,31 @@
|
|||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"express-async-handler": "^1.2.0",
|
"express-async-handler": "^1.2.0",
|
||||||
"express-static-gzip": "2.1.7",
|
"express-static-gzip": "2.1.7",
|
||||||
"fs-extra": "11.1.0",
|
"fs-extra": "11.1.1",
|
||||||
"googleapis": "110.0.0",
|
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"jwt-simple": "^0.5.6",
|
"jwt-simple": "^0.5.6",
|
||||||
"less": "^3.13.1",
|
"less": "^3.13.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"marked": "4.2.12",
|
"marked": "4.3.0",
|
||||||
"marked-extended-tables": "^1.0.5",
|
"marked-extended-tables": "^1.0.5",
|
||||||
"markedLegacy": "npm:marked@^0.3.19",
|
"markedLegacy": "npm:marked@^0.3.19",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"mongoose": "^6.9.0",
|
"mongoose": "^7.0.2",
|
||||||
"nanoid": "3.3.4",
|
"nanoid": "3.3.4",
|
||||||
"nconf": "^0.12.0",
|
"nconf": "^0.12.0",
|
||||||
"npm": "^8.10.0",
|
"npm": "^9.6.2",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-frame-component": "4.1.3",
|
"react-frame-component": "4.1.3",
|
||||||
"react-router-dom": "6.8.0",
|
"react-router-dom": "6.9.0",
|
||||||
"sanitize-filename": "1.6.3",
|
"sanitize-filename": "1.6.3",
|
||||||
"superagent": "^6.1.0",
|
"superagent": "^6.1.0",
|
||||||
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
|
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^8.33.0",
|
"eslint": "^8.36.0",
|
||||||
"eslint-plugin-react": "^7.32.2",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
"jest": "^29.4.1",
|
"jest": "^29.5.0",
|
||||||
"supertest": "^6.3.3"
|
"supertest": "^6.3.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ const transforms = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const build = async ({ bundle, render, ssr })=>{
|
const build = async ({ bundle, render, ssr })=>{
|
||||||
let css = await lessTransform.generate({ paths: './shared' });
|
const css = await lessTransform.generate({ paths: './shared' });
|
||||||
css = `@layer bundle {\n${css}\n}`;
|
//css = `@layer bundle {\n${css}\n}`;
|
||||||
await fs.outputFile('./build/homebrew/bundle.css', css);
|
await fs.outputFile('./build/homebrew/bundle.css', css);
|
||||||
await fs.outputFile('./build/homebrew/bundle.js', bundle);
|
await fs.outputFile('./build/homebrew/bundle.js', bundle);
|
||||||
await fs.outputFile('./build/homebrew/ssr.js', ssr);
|
await fs.outputFile('./build/homebrew/ssr.js', ssr);
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ const mw = {
|
|||||||
.status(401)
|
.status(401)
|
||||||
.send('Authorization Required');
|
.send('Authorization Required');
|
||||||
}
|
}
|
||||||
const [username, password] = new Buffer(req.get('authorization').split(' ').pop(), 'base64')
|
const [username, password] = Buffer.from(req.get('authorization').split(' ').pop(), 'base64')
|
||||||
.toString('ascii')
|
.toString('ascii')
|
||||||
.split(':');
|
.split(':');
|
||||||
if(process.env.ADMIN_USER === username && process.env.ADMIN_PASS === password){
|
if(process.env.ADMIN_USER === username && process.env.ADMIN_PASS === password){
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const splitTextStyleAndMetadata = (brew)=>{
|
|||||||
const index = brew.text.indexOf('```\n\n');
|
const index = brew.text.indexOf('```\n\n');
|
||||||
const metadataSection = brew.text.slice(12, index - 1);
|
const metadataSection = brew.text.slice(12, index - 1);
|
||||||
const metadata = yaml.load(metadataSection);
|
const metadata = yaml.load(metadataSection);
|
||||||
Object.assign(brew, _.pick(metadata, ['title', 'description', 'tags', 'systems', 'renderer', 'theme']));
|
Object.assign(brew, _.pick(metadata, ['title', 'description', 'tags', 'systems', 'renderer', 'theme', 'lang']));
|
||||||
brew.text = brew.text.slice(index + 5);
|
brew.text = brew.text.slice(index + 5);
|
||||||
}
|
}
|
||||||
if(brew.text.startsWith('```css')) {
|
if(brew.text.startsWith('```css')) {
|
||||||
@@ -225,6 +225,7 @@ app.get('/user/:username', async (req, res, next)=>{
|
|||||||
'pageCount',
|
'pageCount',
|
||||||
'description',
|
'description',
|
||||||
'authors',
|
'authors',
|
||||||
|
'lang',
|
||||||
'published',
|
'published',
|
||||||
'views',
|
'views',
|
||||||
'shareId',
|
'shareId',
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ const DEFAULT_BREW = {
|
|||||||
authors : [],
|
authors : [],
|
||||||
tags : [],
|
tags : [],
|
||||||
systems : [],
|
systems : [],
|
||||||
|
lang : 'en',
|
||||||
thumbnail : '',
|
thumbnail : '',
|
||||||
views : 0,
|
views : 0,
|
||||||
published : false,
|
published : false,
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ const disconnect = async ()=>{
|
|||||||
};
|
};
|
||||||
|
|
||||||
const connect = async (config)=>{
|
const connect = async (config)=>{
|
||||||
return await Mongoose.connect(getMongoDBURL(config),
|
return await Mongoose.connect(getMongoDBURL(config), { retryWrites: false })
|
||||||
{ retryWrites: false }, handleConnectionError);
|
.catch((error)=>handleConnectionError(error));
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* eslint-disable max-lines */
|
/* eslint-disable max-lines */
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const { google } = require('googleapis');
|
const googleDrive = require('@googleapis/drive');
|
||||||
const { nanoid } = require('nanoid');
|
const { nanoid } = require('nanoid');
|
||||||
const token = require('./token.js');
|
const token = require('./token.js');
|
||||||
const config = require('./config.js');
|
const config = require('./config.js');
|
||||||
@@ -14,7 +14,7 @@ if(!config.get('service_account')){
|
|||||||
config.get('service_account');
|
config.get('service_account');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
serviceAuth = google.auth.fromJSON(keys);
|
serviceAuth = googleDrive.auth.fromJSON(keys);
|
||||||
serviceAuth.scopes = ['https://www.googleapis.com/auth/drive'];
|
serviceAuth.scopes = ['https://www.googleapis.com/auth/drive'];
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn(err);
|
console.warn(err);
|
||||||
@@ -22,7 +22,7 @@ if(!config.get('service_account')){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
google.options({ auth: serviceAuth || config.get('google_api_key') });
|
const defaultAuth = serviceAuth || config.get('google_api_key');
|
||||||
|
|
||||||
const GoogleActions = {
|
const GoogleActions = {
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ const GoogleActions = {
|
|||||||
throw (err);
|
throw (err);
|
||||||
}
|
}
|
||||||
|
|
||||||
const oAuth2Client = new google.auth.OAuth2(
|
const oAuth2Client = new googleDrive.auth.OAuth2(
|
||||||
config.get('google_client_id'),
|
config.get('google_client_id'),
|
||||||
config.get('google_client_secret'),
|
config.get('google_client_secret'),
|
||||||
'/auth/google/redirect'
|
'/auth/google/redirect'
|
||||||
@@ -60,7 +60,7 @@ const GoogleActions = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getGoogleFolder : async (auth)=>{
|
getGoogleFolder : async (auth)=>{
|
||||||
const drive = google.drive({ version: 'v3', auth });
|
const drive = googleDrive.drive({ version: 'v3', auth });
|
||||||
|
|
||||||
fileMetadata = {
|
fileMetadata = {
|
||||||
'name' : 'Homebrewery',
|
'name' : 'Homebrewery',
|
||||||
@@ -97,7 +97,7 @@ const GoogleActions = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
listGoogleBrews : async (auth)=>{
|
listGoogleBrews : async (auth)=>{
|
||||||
const drive = google.drive({ version: 'v3', auth });
|
const drive = googleDrive.drive({ version: 'v3', auth });
|
||||||
|
|
||||||
const obj = await drive.files.list({
|
const obj = await drive.files.list({
|
||||||
pageSize : 1000,
|
pageSize : 1000,
|
||||||
@@ -129,14 +129,16 @@ const GoogleActions = {
|
|||||||
description : file.description,
|
description : file.description,
|
||||||
views : parseInt(file.properties.views),
|
views : parseInt(file.properties.views),
|
||||||
published : file.properties.published ? file.properties.published == 'true' : false,
|
published : file.properties.published ? file.properties.published == 'true' : false,
|
||||||
systems : []
|
systems : [],
|
||||||
|
lang : file.properties.lang,
|
||||||
|
thumbnail : file.properties.thumbnail
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
return brews;
|
return brews;
|
||||||
},
|
},
|
||||||
|
|
||||||
updateGoogleBrew : async (brew)=>{
|
updateGoogleBrew : async (brew)=>{
|
||||||
const drive = google.drive({ version: 'v3' });
|
const drive = googleDrive.drive({ version: 'v3', auth: defaultAuth });
|
||||||
|
|
||||||
await drive.files.update({
|
await drive.files.update({
|
||||||
fileId : brew.googleId,
|
fileId : brew.googleId,
|
||||||
@@ -149,7 +151,8 @@ const GoogleActions = {
|
|||||||
editId : brew.editId || nanoid(12),
|
editId : brew.editId || nanoid(12),
|
||||||
pageCount : brew.pageCount,
|
pageCount : brew.pageCount,
|
||||||
renderer : brew.renderer || 'legacy',
|
renderer : brew.renderer || 'legacy',
|
||||||
isStubbed : true
|
isStubbed : true,
|
||||||
|
lang : brew.lang || 'en'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
media : {
|
media : {
|
||||||
@@ -167,7 +170,7 @@ const GoogleActions = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
newGoogleBrew : async (auth, brew)=>{
|
newGoogleBrew : async (auth, brew)=>{
|
||||||
const drive = google.drive({ version: 'v3', auth });
|
const drive = googleDrive.drive({ version: 'v3', auth });
|
||||||
|
|
||||||
const media = {
|
const media = {
|
||||||
mimeType : 'text/plain',
|
mimeType : 'text/plain',
|
||||||
@@ -187,7 +190,8 @@ const GoogleActions = {
|
|||||||
pageCount : brew.pageCount,
|
pageCount : brew.pageCount,
|
||||||
renderer : brew.renderer || 'legacy',
|
renderer : brew.renderer || 'legacy',
|
||||||
isStubbed : true,
|
isStubbed : true,
|
||||||
version : 1
|
version : 1,
|
||||||
|
lang : brew.lang || 'en'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -218,7 +222,7 @@ const GoogleActions = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getGoogleBrew : async (id, accessId, accessType)=>{
|
getGoogleBrew : async (id, accessId, accessType)=>{
|
||||||
const drive = google.drive({ version: 'v3' });
|
const drive = googleDrive.drive({ version: 'v3', auth: defaultAuth });
|
||||||
|
|
||||||
const obj = await drive.files.get({
|
const obj = await drive.files.get({
|
||||||
fileId : id,
|
fileId : id,
|
||||||
@@ -255,6 +259,7 @@ const GoogleActions = {
|
|||||||
description : obj.data.description,
|
description : obj.data.description,
|
||||||
systems : obj.data.properties.systems ? obj.data.properties.systems.split(',') : [],
|
systems : obj.data.properties.systems ? obj.data.properties.systems.split(',') : [],
|
||||||
authors : [],
|
authors : [],
|
||||||
|
lang : obj.data.properties.lang,
|
||||||
published : obj.data.properties.published ? obj.data.properties.published == 'true' : false,
|
published : obj.data.properties.published ? obj.data.properties.published == 'true' : false,
|
||||||
trashed : obj.data.trashed,
|
trashed : obj.data.trashed,
|
||||||
|
|
||||||
@@ -274,7 +279,7 @@ const GoogleActions = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
deleteGoogleBrew : async (auth, id, accessId)=>{
|
deleteGoogleBrew : async (auth, id, accessId)=>{
|
||||||
const drive = google.drive({ version: 'v3', auth });
|
const drive = googleDrive.drive({ version: 'v3', auth });
|
||||||
|
|
||||||
const obj = await drive.files.get({
|
const obj = await drive.files.get({
|
||||||
fileId : id,
|
fileId : id,
|
||||||
@@ -300,7 +305,7 @@ const GoogleActions = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
increaseView : async (id, accessId, accessType, brew)=>{
|
increaseView : async (id, accessId, accessType, brew)=>{
|
||||||
const drive = google.drive({ version: 'v3' });
|
const drive = googleDrive.drive({ version: 'v3', auth: defaultAuth });
|
||||||
|
|
||||||
await drive.files.update({
|
await drive.files.update({
|
||||||
fileId : brew.googleId,
|
fileId : brew.googleId,
|
||||||
|
|||||||
@@ -317,8 +317,7 @@ If you believe you should have access to this brew, ask the file owner to invite
|
|||||||
brew.textBin = zlib.deflateRawSync(brew.text);
|
brew.textBin = zlib.deflateRawSync(brew.text);
|
||||||
brew.text = undefined;
|
brew.text = undefined;
|
||||||
}
|
}
|
||||||
|
brew.markModified('authors'); //Mongo will not properly update arrays without markModified()
|
||||||
// Otherwise, save the brew with updated author list
|
|
||||||
await brew.save()
|
await brew.save()
|
||||||
.catch((err)=>{
|
.catch((err)=>{
|
||||||
throw { status: 500, message: err };
|
throw { status: 500, message: err };
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ describe('Tests for api', ()=>{
|
|||||||
let modelBrew;
|
let modelBrew;
|
||||||
let saveFunc;
|
let saveFunc;
|
||||||
let removeFunc;
|
let removeFunc;
|
||||||
|
let markModifiedFunc;
|
||||||
let saved;
|
let saved;
|
||||||
|
|
||||||
beforeEach(()=>{
|
beforeEach(()=>{
|
||||||
@@ -20,15 +21,18 @@ describe('Tests for api', ()=>{
|
|||||||
return saved;
|
return saved;
|
||||||
});
|
});
|
||||||
removeFunc = jest.fn(async function() {});
|
removeFunc = jest.fn(async function() {});
|
||||||
|
markModifiedFunc = jest.fn(()=>true);
|
||||||
|
|
||||||
modelBrew = (brew)=>({
|
modelBrew = (brew)=>({
|
||||||
...brew,
|
...brew,
|
||||||
save : saveFunc,
|
save : saveFunc,
|
||||||
remove : removeFunc,
|
remove : removeFunc,
|
||||||
toObject : function() {
|
markModified : markModifiedFunc,
|
||||||
|
toObject : function() {
|
||||||
delete this.save;
|
delete this.save;
|
||||||
delete this.toObject;
|
delete this.toObject;
|
||||||
delete this.remove;
|
delete this.remove;
|
||||||
|
delete this.markModified;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -58,6 +62,7 @@ describe('Tests for api', ()=>{
|
|||||||
description : 'this is a description',
|
description : 'this is a description',
|
||||||
tags : ['something', 'fun'],
|
tags : ['something', 'fun'],
|
||||||
systems : ['D&D 5e'],
|
systems : ['D&D 5e'],
|
||||||
|
lang : 'en',
|
||||||
renderer : 'v3',
|
renderer : 'v3',
|
||||||
theme : 'phb',
|
theme : 'phb',
|
||||||
published : true,
|
published : true,
|
||||||
@@ -251,6 +256,7 @@ If you believe you should have access to this brew, ask the file owner to invite
|
|||||||
pageCount : 1,
|
pageCount : 1,
|
||||||
published : false,
|
published : false,
|
||||||
renderer : 'legacy',
|
renderer : 'legacy',
|
||||||
|
lang : 'en',
|
||||||
shareId : undefined,
|
shareId : undefined,
|
||||||
systems : [],
|
systems : [],
|
||||||
tags : [],
|
tags : [],
|
||||||
@@ -444,6 +450,7 @@ brew`);
|
|||||||
pageCount : 1,
|
pageCount : 1,
|
||||||
published : false,
|
published : false,
|
||||||
renderer : 'V3',
|
renderer : 'V3',
|
||||||
|
lang : 'en',
|
||||||
shareId : expect.any(String),
|
shareId : expect.any(String),
|
||||||
style : undefined,
|
style : undefined,
|
||||||
systems : [],
|
systems : [],
|
||||||
@@ -502,6 +509,7 @@ brew`);
|
|||||||
pageCount : undefined,
|
pageCount : undefined,
|
||||||
published : false,
|
published : false,
|
||||||
renderer : undefined,
|
renderer : undefined,
|
||||||
|
lang : 'en',
|
||||||
shareId : expect.any(String),
|
shareId : expect.any(String),
|
||||||
googleId : expect.any(String),
|
googleId : expect.any(String),
|
||||||
style : undefined,
|
style : undefined,
|
||||||
@@ -627,6 +635,7 @@ brew`);
|
|||||||
await api.deleteBrew(req, res);
|
await api.deleteBrew(req, res);
|
||||||
|
|
||||||
expect(api.getBrew).toHaveBeenCalled();
|
expect(api.getBrew).toHaveBeenCalled();
|
||||||
|
expect(markModifiedFunc).toHaveBeenCalled();
|
||||||
expect(model.findOne).toHaveBeenCalled();
|
expect(model.findOne).toHaveBeenCalled();
|
||||||
expect(removeFunc).not.toHaveBeenCalled();
|
expect(removeFunc).not.toHaveBeenCalled();
|
||||||
expect(saveFunc).toHaveBeenCalled();
|
expect(saveFunc).toHaveBeenCalled();
|
||||||
@@ -716,6 +725,7 @@ brew`);
|
|||||||
await api.deleteBrew(req, res);
|
await api.deleteBrew(req, res);
|
||||||
|
|
||||||
expect(api.getBrew).toHaveBeenCalled();
|
expect(api.getBrew).toHaveBeenCalled();
|
||||||
|
expect(markModifiedFunc).toHaveBeenCalled();
|
||||||
expect(model.findOne).toHaveBeenCalled();
|
expect(model.findOne).toHaveBeenCalled();
|
||||||
expect(removeFunc).not.toHaveBeenCalled();
|
expect(removeFunc).not.toHaveBeenCalled();
|
||||||
expect(api.deleteGoogleBrew).toHaveBeenCalled();
|
expect(api.deleteGoogleBrew).toHaveBeenCalled();
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ const HomebrewSchema = mongoose.Schema({
|
|||||||
description : { type: String, default: '' },
|
description : { type: String, default: '' },
|
||||||
tags : [String],
|
tags : [String],
|
||||||
systems : [String],
|
systems : [String],
|
||||||
|
lang : { type: String, default: 'en' },
|
||||||
renderer : { type: String, default: '' },
|
renderer : { type: String, default: '' },
|
||||||
authors : [String],
|
authors : [String],
|
||||||
invitedAuthors : [String],
|
invitedAuthors : [String],
|
||||||
@@ -39,30 +40,24 @@ HomebrewSchema.statics.increaseView = async function(query) {
|
|||||||
return brew;
|
return brew;
|
||||||
};
|
};
|
||||||
|
|
||||||
HomebrewSchema.statics.get = function(query, fields=null){
|
HomebrewSchema.statics.get = async function(query, fields=null){
|
||||||
return new Promise((resolve, reject)=>{
|
const brew = await Homebrew.findOne(query, fields).orFail()
|
||||||
Homebrew.find(query, fields, null, (err, brews)=>{
|
.catch((error)=>{throw 'Can not find brew';});
|
||||||
if(err || !brews.length) return reject('Can not find brew');
|
if(!_.isNil(brew.textBin)) { // Uncompress zipped text field
|
||||||
if(!_.isNil(brews[0].textBin)) { // Uncompress zipped text field
|
unzipped = zlib.inflateRawSync(brew.textBin);
|
||||||
unzipped = zlib.inflateRawSync(brews[0].textBin);
|
brew.text = unzipped.toString();
|
||||||
brews[0].text = unzipped.toString();
|
}
|
||||||
}
|
return brew;
|
||||||
return resolve(brews[0]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
HomebrewSchema.statics.getByUser = function(username, allowAccess=false, fields=null){
|
HomebrewSchema.statics.getByUser = async function(username, allowAccess=false, fields=null){
|
||||||
return new Promise((resolve, reject)=>{
|
const query = { authors: username, published: true };
|
||||||
const query = { authors: username, published: true };
|
if(allowAccess){
|
||||||
if(allowAccess){
|
delete query.published;
|
||||||
delete query.published;
|
}
|
||||||
}
|
const brews = await Homebrew.find(query, fields).lean().exec() //lean() converts results to JSObjects
|
||||||
Homebrew.find(query, fields).lean().exec((err, brews)=>{ //lean() converts results to JSObjects
|
.catch((error)=>{throw 'Can not find brews';});
|
||||||
if(err) return reject('Can not find brew');
|
return brews;
|
||||||
return resolve(brews);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const Homebrew = mongoose.model('Homebrew', HomebrewSchema);
|
const Homebrew = mongoose.model('Homebrew', HomebrewSchema);
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ const definitionLists = {
|
|||||||
Marked.use({ extensions: [mustacheSpans, mustacheDivs, mustacheInjectInline, definitionLists] });
|
Marked.use({ extensions: [mustacheSpans, mustacheDivs, mustacheInjectInline, definitionLists] });
|
||||||
Marked.use(MarkedExtendedTables());
|
Marked.use(MarkedExtendedTables());
|
||||||
Marked.use(mustacheInjectBlock);
|
Marked.use(mustacheInjectBlock);
|
||||||
Marked.use({ smartypants: true });
|
Marked.use({ renderer: renderer, smartypants: true });
|
||||||
|
|
||||||
//Fix local links in the Preview iFrame to link inside the frame
|
//Fix local links in the Preview iFrame to link inside the frame
|
||||||
renderer.link = function (href, title, text) {
|
renderer.link = function (href, title, text) {
|
||||||
@@ -347,10 +347,7 @@ module.exports = {
|
|||||||
render : (rawBrewText)=>{
|
render : (rawBrewText)=>{
|
||||||
rawBrewText = rawBrewText.replace(/^\\column$/gm, `\n<div class='columnSplit'></div>\n`)
|
rawBrewText = rawBrewText.replace(/^\\column$/gm, `\n<div class='columnSplit'></div>\n`)
|
||||||
.replace(/^(:+)$/gm, (match)=>`${`<div class='blank'></div>`.repeat(match.length)}\n`);
|
.replace(/^(:+)$/gm, (match)=>`${`<div class='blank'></div>`.repeat(match.length)}\n`);
|
||||||
return Marked.parse(
|
return Marked.parse(sanatizeScriptTags(rawBrewText));
|
||||||
sanatizeScriptTags(rawBrewText),
|
|
||||||
{ renderer: renderer }
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
validate : (rawBrewText)=>{
|
validate : (rawBrewText)=>{
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
vertical-align : middle;
|
vertical-align : middle;
|
||||||
text-align : center;
|
text-align : center;
|
||||||
i{
|
i{
|
||||||
display : block;
|
display : block !important;
|
||||||
margin : 10px 0px;
|
margin : 10px 0px;
|
||||||
font-size : 6px;
|
font-size : 6px;
|
||||||
color : #666;
|
color : #666;
|
||||||
|
|||||||
@@ -13,3 +13,9 @@ test('Processes the markdown within an HTML block if its just a class wrapper',
|
|||||||
const rendered = Markdown.render(source);
|
const rendered = Markdown.render(source);
|
||||||
expect(rendered).toBe('<div> <p><em>Bold text</em></p>\n </div>');
|
expect(rendered).toBe('<div> <p><em>Bold text</em></p>\n </div>');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Check markdown is using the custom renderer; specifically that it adds target=_self attribute to internal links in HTML blocks', function() {
|
||||||
|
const source = '<div>[Has _self Attribute?](#p1)</div>';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
expect(rendered).toBe('<div> <p><a href="#p1" target="_self">Has _self Attribute?</a></p>\n </div>');
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,499 +1,498 @@
|
|||||||
@layer Legacy_5ePHB {
|
@import (less) './themes/fonts/5e legacy/fonts.less';
|
||||||
@import (less) './themes/fonts/5e legacy/fonts.less';
|
@import (less) './themes/assets/assets.less';
|
||||||
@import (less) './themes/assets/assets.less';
|
@import (less) './themes/phb.depricated.less';
|
||||||
@import (less) './themes/phb.depricated.less';
|
//Colors
|
||||||
//Colors
|
@background : #EEE5CE; // Light parchment
|
||||||
@background : #EEE5CE; // Light parchment
|
@noteGreen : #e0e5c1; // Pastel green
|
||||||
@noteGreen : #e0e5c1; // Pastel green
|
@headerUnderline : #c9ad6a; // Gold
|
||||||
@headerUnderline : #c9ad6a; // Gold
|
@horizontalRule : #9c2b1b; // Maroon
|
||||||
@horizontalRule : #9c2b1b; // Maroon
|
@headerText : #58180D; // Dark maroon
|
||||||
@headerText : #58180D; // Dark maroon
|
@monsterStatBackground : #FDF1DC; // Lighter parchment
|
||||||
@monsterStatBackground : #FDF1DC; // Lighter parchment
|
@captionText : #766649; // Brown
|
||||||
@captionText : #766649; // Brown
|
@page { margin: 0; }
|
||||||
@page { margin: 0; }
|
body {
|
||||||
body {
|
counter-reset : phb-page-numbers;
|
||||||
counter-reset : phb-page-numbers;
|
}
|
||||||
}
|
*{
|
||||||
*{
|
-webkit-print-color-adjust : exact;
|
||||||
-webkit-print-color-adjust : exact;
|
}
|
||||||
}
|
.useSansSerif(){
|
||||||
.useSansSerif(){
|
font-family : ScalySans;
|
||||||
|
em{
|
||||||
font-family : ScalySans;
|
font-family : ScalySans;
|
||||||
em{
|
font-style : italic;
|
||||||
font-family : ScalySans;
|
}
|
||||||
font-style : italic;
|
strong{
|
||||||
}
|
font-family : ScalySans;
|
||||||
strong{
|
font-weight : 800;
|
||||||
font-family : ScalySans;
|
letter-spacing : -0.02em;
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.useColumns(@multiplier : 1){
|
ul{
|
||||||
column-count : 2;
|
margin-bottom : 0.8em;
|
||||||
column-fill : auto;
|
padding-left : 1.4em;
|
||||||
column-gap : 1cm;
|
line-height : 1.269em;
|
||||||
column-width : 8cm * @multiplier;
|
list-style-position : outside;
|
||||||
-webkit-column-count : 2;
|
list-style-type : disc;
|
||||||
-moz-column-count : 2;
|
|
||||||
-webkit-column-width : 8cm * @multiplier;
|
|
||||||
-moz-column-width : 8cm * @multiplier;
|
|
||||||
-webkit-column-gap : 1cm;
|
|
||||||
-moz-column-gap : 1cm;
|
|
||||||
}
|
}
|
||||||
.phb{
|
ol{
|
||||||
.useColumns();
|
margin-bottom : 0.8em;
|
||||||
counter-increment : phb-page-numbers;
|
padding-left : 1.4em;
|
||||||
position : relative;
|
line-height : 1.269em;
|
||||||
z-index : 15;
|
list-style-position : outside;
|
||||||
box-sizing : border-box;
|
list-style-type : decimal;
|
||||||
overflow : hidden;
|
}
|
||||||
height : 279.4mm;
|
//Indents after p or lists
|
||||||
width : 215.9mm;
|
p+p, ul+p, ol+p{
|
||||||
padding : 1.0cm 1.7cm;
|
text-indent : 1em;
|
||||||
padding-bottom : 1.5cm;
|
}
|
||||||
background-color : @background;
|
img{
|
||||||
background-image : @backgroundImage;
|
z-index : -1;
|
||||||
font-family : BookSanity;
|
}
|
||||||
font-size : 0.317cm;
|
strong{
|
||||||
text-rendering : optimizeLegibility;
|
font-weight : bold;
|
||||||
page-break-before : always;
|
letter-spacing : 0.03em;
|
||||||
page-break-after : always;
|
}
|
||||||
contain : size;
|
em{
|
||||||
//*****************************
|
font-style : italic;
|
||||||
// * BASE
|
}
|
||||||
// *****************************/
|
sup{
|
||||||
p{
|
vertical-align : super;
|
||||||
padding-bottom : 0.8em;
|
font-size : smaller;
|
||||||
line-height : 1.269em;
|
line-height : 0;
|
||||||
&+p{
|
}
|
||||||
margin-top : -0.8em;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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{
|
tbody{
|
||||||
margin-bottom : 0.8em;
|
tr{
|
||||||
padding-left : 1.4em;
|
td{
|
||||||
line-height : 1.269em;
|
padding : 0.3em 0.1em;
|
||||||
list-style-position : outside;
|
}
|
||||||
list-style-type : disc;
|
&:nth-child(odd){
|
||||||
}
|
background-color : @noteGreen;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
//*****************************
|
|
||||||
// * 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{
|
|
||||||
transform : scaleX(-1);
|
|
||||||
}
|
|
||||||
.pageNumber{
|
|
||||||
left : 2px;
|
|
||||||
}
|
|
||||||
.footnote{
|
|
||||||
left : 80px;
|
|
||||||
text-align : left;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//*****************************
|
//*****************************
|
||||||
// * SPELL LIST
|
// * NOTE
|
||||||
// *****************************/
|
// *****************************/
|
||||||
.phb .spellList{
|
blockquote{
|
||||||
.useSansSerif();
|
.useSansSerif();
|
||||||
column-count : 4;
|
box-sizing : border-box;
|
||||||
column-span : all;
|
margin-bottom : 1em;
|
||||||
-webkit-column-span : all;
|
padding : 5px 10px;
|
||||||
-moz-column-span : all;
|
background-color : @noteGreen;
|
||||||
ul+h5{
|
border-style : solid;
|
||||||
margin-top : 15px;
|
border-width : 11px;
|
||||||
}
|
border-image : @noteBorderImage 11;
|
||||||
|
border-image-outset : 9px 0px;
|
||||||
|
box-shadow : 1px 4px 14px #888;
|
||||||
p, ul{
|
p, ul{
|
||||||
font-size : 0.352cm;
|
font-size : 0.352cm;
|
||||||
line-height : 1.263em;
|
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{
|
||||||
|
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{
|
ul{
|
||||||
margin-bottom : 0.5em;
|
.useSansSerif();
|
||||||
padding-left : 1em;
|
padding-left : 1em;
|
||||||
text-indent : -1em;
|
font-size : 0.352cm;
|
||||||
list-style-type : none;
|
|
||||||
-webkit-column-break-inside : auto;
|
|
||||||
page-break-inside : auto;
|
|
||||||
break-inside : auto;
|
|
||||||
}
|
}
|
||||||
}
|
// Monster Ability table
|
||||||
//*****************************
|
hr+table{
|
||||||
// * WIDE
|
margin : 0;
|
||||||
// *****************************/
|
background-color : transparent;
|
||||||
.phb .wide{
|
border-style : none;
|
||||||
column-span : all;
|
border-image : none;
|
||||||
-webkit-column-span : all;
|
tbody{
|
||||||
-moz-column-span : all;
|
tr:nth-child(odd), tr:nth-child(even){
|
||||||
}
|
background-color : transparent;
|
||||||
//*****************************
|
|
||||||
// * 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 : inherit;
|
|
||||||
text-decoration : unset;
|
|
||||||
&:hover {
|
|
||||||
text-decoration : underline;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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);
|
||||||
|
column-fill : balance;
|
||||||
}
|
}
|
||||||
//*****************************
|
//*****************************
|
||||||
// * TABLE OF CONTENTS
|
// * FOOTER
|
||||||
// *****************************/
|
// *****************************/
|
||||||
.phb .toc{
|
&: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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.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;
|
-webkit-column-break-inside : avoid;
|
||||||
page-break-inside : avoid;
|
page-break-inside : avoid;
|
||||||
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//*****************************
|
||||||
|
// * 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{
|
a{
|
||||||
color : black;
|
color : inherit;
|
||||||
text-decoration : none;
|
text-decoration : unset;
|
||||||
&:hover{
|
&:hover {
|
||||||
text-decoration : underline;
|
text-decoration : underline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ul{
|
}
|
||||||
padding-left : 0;
|
}
|
||||||
list-style-type : none;
|
//*****************************
|
||||||
}
|
// * TABLE OF CONTENTS
|
||||||
&>ul>li{
|
// *****************************/
|
||||||
margin-bottom : 10px;
|
.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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
@layer V3_5eDMG {
|
:root {
|
||||||
:root {
|
//Colors
|
||||||
//Colors
|
--HB_Color_Accent : #EBCEC3; // Salmon
|
||||||
--HB_Color_Accent : #EBCEC3; // Salmon
|
--HB_Color_Footnotes : #5C5C5C; // Dark gray
|
||||||
--HB_Color_Footnotes : #5C5C5C; // Dark gray
|
}
|
||||||
|
|
||||||
|
.page {
|
||||||
|
background-image : url(/assets/DMG_background.png);
|
||||||
|
background-size : cover;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
background-image : url(/assets/DMG_footerAccent.png);
|
||||||
|
height: 58px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page {
|
.footnote {
|
||||||
background-image : url(/assets/DMG_background.png);
|
bottom : 40px;
|
||||||
background-size : cover;
|
|
||||||
|
|
||||||
&:after {
|
|
||||||
background-image : url(/assets/DMG_footerAccent.png);
|
|
||||||
height: 58px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footnote {
|
|
||||||
bottom : 40px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
const MagicGen = require('./snippets/magic.gen.js');
|
const MagicGen = require('./snippets/magic.gen.js');
|
||||||
const ClassTableGen = require('./snippets/classtable.gen.js');
|
const ClassTableGen = require('./snippets/classtable.gen.js');
|
||||||
const MonsterBlockGen = require('./snippets/monsterblock.gen.js');
|
const MonsterBlockGen = require('./snippets/monsterblock.gen.js');
|
||||||
|
const scriptGen = require('./snippets/script.gen.js');
|
||||||
const ClassFeatureGen = require('./snippets/classfeature.gen.js');
|
const ClassFeatureGen = require('./snippets/classfeature.gen.js');
|
||||||
const CoverPageGen = require('./snippets/coverpage.gen.js');
|
const CoverPageGen = require('./snippets/coverpage.gen.js');
|
||||||
const TableOfContentsGen = require('./snippets/tableOfContents.gen.js');
|
const TableOfContentsGen = require('./snippets/tableOfContents.gen.js');
|
||||||
@@ -169,9 +170,10 @@ module.exports = [
|
|||||||
gen : MonsterBlockGen.monster('monster,frame,wide', 4),
|
gen : MonsterBlockGen.monster('monster,frame,wide', 4),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name : 'Cover Page',
|
name : 'Cover Page',
|
||||||
icon : 'fas fa-file-word',
|
icon : 'fac book-front-cover',
|
||||||
gen : CoverPageGen,
|
gen : CoverPageGen,
|
||||||
|
experimental : true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name : 'Magic Item',
|
name : 'Magic Item',
|
||||||
@@ -231,7 +233,30 @@ module.exports = [
|
|||||||
name : '1/3 Class Table (unframed)',
|
name : '1/3 Class Table (unframed)',
|
||||||
icon : 'fas fa-border-none',
|
icon : 'fas fa-border-none',
|
||||||
gen : ClassTableGen.third('classTable'),
|
gen : ClassTableGen.third('classTable'),
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -1,55 +1,46 @@
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
const dedent = require('dedent-tabs').default;
|
||||||
|
|
||||||
const titles = [
|
const titles = [
|
||||||
'The Burning Gallows',
|
'The Burning Gallows', 'The Ring of Nenlast',
|
||||||
'The Ring of Nenlast',
|
'Below the Blind Tavern', 'Below the Hungering River',
|
||||||
'Below the Blind Tavern',
|
'Before Bahamut\'s Land', 'The Cruel Grave from Within',
|
||||||
'Below the Hungering River',
|
'The Strength of Trade Road', 'Through The Raven Queen\'s Worlds',
|
||||||
'Before Bahamut\'s Land',
|
'Within the Settlement', 'The Crown from Within',
|
||||||
'The Cruel Grave from Within',
|
'The Merchant Within the Battlefield', 'Ioun\'s Fading Traveler',
|
||||||
'The Strength of Trade Road',
|
'The Legion Ingredient', 'The Explorer Lure',
|
||||||
'Through The Raven Queen\'s Worlds',
|
'Before the Charming Badlands', 'Vecna\'s Hidden Sage',
|
||||||
'Within the Settlement',
|
'The Living Dead Above the Fearful Cage', 'Bahamut\'s Demonspawn',
|
||||||
'The Crown from Within',
|
'Across Gruumsh\'s Elemental Chaos', 'The Blade of Orcus',
|
||||||
'The Merchant Within the Battlefield',
|
'Beyond Revenge', 'Brain of Insanity',
|
||||||
'Ioun\'s Fading Traveler',
|
'Breed Battle!, A New Beginning', 'Evil Lake, A New Beginning',
|
||||||
'The Legion Ingredient',
|
'Invasion of the Gigantic Cat, Part II', 'Kraken War 2020',
|
||||||
'The Explorer Lure',
|
'The Body Whisperers', 'The Doctor from Heaven',
|
||||||
'Before the Charming Badlands',
|
'The Diabolical Tales of the Ape-Women', 'The Doctor Immortal',
|
||||||
'The Living Dead Above the Fearful Cage',
|
'Core of Heaven: Guardian of Amazement', 'The Graveyard',
|
||||||
'Vecna\'s Hidden Sage',
|
'Guardian: Skies of the Dark Wizard', 'Lute of Eternity',
|
||||||
'Bahamut\'s Demonspawn',
|
'Mercury\'s Planet: Brave Evolution', 'Azure Core',
|
||||||
'Across Gruumsh\'s Elemental Chaos',
|
'Sky of Zelda: The Thunder of Force', 'Core Battle',
|
||||||
'The Blade of Orcus',
|
'Ruby of Atlantis: The Quake of Peace', 'Deadly Amazement III',
|
||||||
'Beyond Revenge',
|
'Dry Chaos IX', 'Gate Thunder',
|
||||||
'Brain of Insanity',
|
'Vyse\'s Skies', 'White Greatness III',
|
||||||
'Breed Battle!, A New Beginning',
|
'Yellow Divinity', 'Zidane\'s Ghost'
|
||||||
'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'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const subtitles = [
|
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 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 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.',
|
'In a land of corruption, two cyberneticists and a dungeon delver search for freedom.',
|
||||||
@@ -74,51 +65,26 @@ const subtitles = [
|
|||||||
'On a planet of mysticism, three travelers and a fire fighter quest for the ultimate weapon and oppose evil.',
|
'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 wicked universe, five seers fight lawlessness.',
|
||||||
'In a kingdom of death, in an era of illusion and blood, four colonists search for fame.',
|
'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 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.'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
module.exports = ()=>{
|
module.exports = ()=>{
|
||||||
return `<style>
|
return dedent`
|
||||||
.page#p1{ text-align:center; counter-increment: none; }
|
{{coverPage }}
|
||||||
.page#p1:after{ display:none; }
|
|
||||||
.page:nth-child(2n) .pageNumber { left: inherit !important; right: 2px !important; }
|
|
||||||
.page:nth-child(2n+1) .pageNumber { right: inherit !important; left: 2px !important; }
|
|
||||||
.page:nth-child(2n)::after { transform: scaleX(1); }
|
|
||||||
.page:nth-child(2n+1)::after { transform: scaleX(-1); }
|
|
||||||
.page:nth-child(2n) .footnote { left: inherit; text-align: right; }
|
|
||||||
.page:nth-child(2n+1) .footnote { left: 80px; text-align: left; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
{{margin-top:225px}}
|
{{logo }}
|
||||||
|
|
||||||
# ${_.sample(titles)}
|
# ${_.sample(titles)}
|
||||||
|
## ${_.sample(subtitles)}
|
||||||
|
__________
|
||||||
|
|
||||||
{{margin-top:25px}}
|
{{banner HOMEBREW}}
|
||||||
|
|
||||||
{{wide
|
{{footnote
|
||||||
##### ${_.sample(subtitles)}
|
${_.sample(footnote)}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
\\page`;
|

|
||||||
};
|
|
||||||
|
\page`;
|
||||||
|
};
|
||||||
|
|||||||
48
themes/V3/5ePHB/snippets/script.gen.js
Normal file
@@ -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`;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
()=>{
|
||||||
|
|
||||||
|
};
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
/* eslint-disable max-lines */
|
/* eslint-disable max-lines */
|
||||||
|
|
||||||
const WatercolorGen = require('./snippets/watercolor.gen.js');
|
const WatercolorGen = require('./snippets/watercolor.gen.js');
|
||||||
const dedent = require('dedent-tabs').default;
|
const ImageMaskGen = require('./snippets/imageMask.gen.js');
|
||||||
|
const dedent = require('dedent-tabs').default;
|
||||||
|
|
||||||
|
|
||||||
module.exports = [
|
module.exports = [
|
||||||
|
|
||||||
@@ -102,6 +101,62 @@ module.exports = [
|
|||||||
icon : 'fas fa-fill-drip',
|
icon : 'fas fa-fill-drip',
|
||||||
gen : WatercolorGen,
|
gen : WatercolorGen,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
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',
|
name : 'Watermark',
|
||||||
icon : 'fas fa-id-card',
|
icon : 'fas fa-id-card',
|
||||||
|
|||||||
36
themes/V3/Blank/snippets/imageMask.gen.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
const _ = require('lodash');
|
||||||
|
const dedent = require('dedent-tabs').default;
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
edge : (side = 'bottom')=>{
|
||||||
|
const rotation = {
|
||||||
|
'bottom' : 0,
|
||||||
|
'top' : 180,
|
||||||
|
'left' : 90,
|
||||||
|
'right' : 270
|
||||||
|
}[side];
|
||||||
|
return dedent`
|
||||||
|
{{imageMaskEdge${_.random(1, 8)},--offset:0cm,--rotation:${rotation}
|
||||||
|
{height:100%}
|
||||||
|
}}
|
||||||
|
<!-- Use --offset to shift the mask toward or away from the page center.
|
||||||
|
Use --rotation to set rotation angle in degrees. -->\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
|
||||||
|
{height:100%}
|
||||||
|
}}
|
||||||
|
<!-- Use --offsetX to shift the mask left or right (can use cm instead of %)
|
||||||
|
Use --offsetY to shift the mask up or down
|
||||||
|
Use --rotation to set rotation angle in degrees. -->\n\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
()=>{
|
||||||
|
|
||||||
|
};
|
||||||
@@ -1,278 +1,410 @@
|
|||||||
@layer V3_Blank {
|
@import (less) './themes/fonts/5e/fonts.less';
|
||||||
@import (less) './themes/fonts/5e/fonts.less';
|
@import (less) './themes/assets/assets.less';
|
||||||
@import (less) './themes/assets/assets.less';
|
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
//Colors
|
//Colors
|
||||||
--HB_Color_Background : #FFFFFF; // White
|
--HB_Color_Background : #FFFFFF; // White
|
||||||
--HB_Color_WatercolorStain : #000000; // Black
|
--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%;
|
||||||
|
}
|
||||||
|
.inline-block {
|
||||||
|
display : inline-block;
|
||||||
|
text-indent : initial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@page { margin: 0; }
|
//*****************************
|
||||||
body {
|
// * HEADERS
|
||||||
counter-reset : phb-page-numbers;
|
// *****************************/
|
||||||
|
h1,h2,h3,h4,h5,h6{
|
||||||
|
font-weight : bold;
|
||||||
|
line-height : 1.2em;
|
||||||
}
|
}
|
||||||
*{
|
h1{
|
||||||
-webkit-print-color-adjust : exact;
|
font-size : 2em;
|
||||||
}
|
}
|
||||||
|
h2{
|
||||||
.useColumns(@multiplier : 1, @fillMode: balance){
|
font-size : 1.5em;
|
||||||
column-fill : @fillMode;
|
|
||||||
column-count : 2;
|
|
||||||
}
|
}
|
||||||
.columnWrapper{
|
h3{
|
||||||
max-height : 100%;
|
font-size : 1.17em;
|
||||||
column-span : all;
|
|
||||||
columns : inherit;
|
|
||||||
column-gap : inherit;
|
|
||||||
}
|
}
|
||||||
.page{
|
h4{
|
||||||
.useColumns();
|
font-size : 1em;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
//*****************************
|
h5{
|
||||||
// * BASE
|
font-size : 0.83em;
|
||||||
// *****************************/
|
}
|
||||||
.page{
|
//*****************************
|
||||||
p{
|
// * TABLE
|
||||||
overflow-wrap : break-word;
|
// *****************************/
|
||||||
display : block;
|
table{
|
||||||
}
|
width : 100%;
|
||||||
strong{
|
thead{
|
||||||
|
display : table-row-group;
|
||||||
font-weight : bold;
|
font-weight : bold;
|
||||||
}
|
}
|
||||||
em{
|
}
|
||||||
font-style : italic;
|
div:not(.columnWrapper) > table + table { // Side-by-side tables should not
|
||||||
}
|
margin-top : 0; // have vertical spacing.
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
//*****************************
|
|
||||||
// * 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
div:not(.columnWrapper) > table + table { // Side-by-side tables should not
|
|
||||||
margin-top : 0; // have vertical spacing.
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Watermark */
|
|
||||||
.watermark {
|
|
||||||
display : grid !important;
|
|
||||||
place-items : center;
|
|
||||||
justify-content : center;
|
|
||||||
position : absolute;
|
|
||||||
margin : 0;
|
|
||||||
top : 0;
|
|
||||||
left : 0;
|
|
||||||
width : 100%;
|
|
||||||
height : 100%;
|
|
||||||
font-size : 120px;
|
|
||||||
text-transform : uppercase;
|
|
||||||
color : black;
|
|
||||||
mix-blend-mode : overlay;
|
|
||||||
opacity : 30%;
|
|
||||||
transform : rotate(-45deg);
|
|
||||||
z-index : 500;
|
|
||||||
p {
|
|
||||||
margin-bottom : none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Watercolor */
|
|
||||||
[class*="watercolor"] {
|
|
||||||
position : absolute;
|
|
||||||
width : 2000px; /* dimensions need to be real big so the user can set */
|
|
||||||
height : 2000px; /* height or width and the image will maintain aspect ratio */
|
|
||||||
-webkit-mask-image : var(--wc);
|
|
||||||
-webkit-mask-size : contain;
|
|
||||||
-webkit-mask-repeat : no-repeat;
|
|
||||||
mask-image : var(--wc);
|
|
||||||
mask-size : contain;
|
|
||||||
mask-repeat : no-repeat;
|
|
||||||
background-size : cover;
|
|
||||||
background-color : var(--HB_Color_WatercolorStain); /*default color*/
|
|
||||||
--wc : @watercolor1; /*default image*/
|
|
||||||
z-index : -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.watercolor1 { --wc : @watercolor1; }
|
|
||||||
.watercolor2 { --wc : @watercolor2; }
|
|
||||||
.watercolor3 { --wc : @watercolor3; }
|
|
||||||
.watercolor4 { --wc : @watercolor4; }
|
|
||||||
.watercolor5 { --wc : @watercolor5; }
|
|
||||||
.watercolor6 { --wc : @watercolor6; }
|
|
||||||
.watercolor7 { --wc : @watercolor7; }
|
|
||||||
.watercolor8 { --wc : @watercolor8; }
|
|
||||||
.watercolor9 { --wc : @watercolor9; }
|
|
||||||
.watercolor10 { --wc : @watercolor10; }
|
|
||||||
.watercolor11 { --wc : @watercolor11; }
|
|
||||||
.watercolor12 { --wc : @watercolor12; }
|
|
||||||
|
|
||||||
//************************************
|
|
||||||
// * CODE BLOCKS
|
|
||||||
// ************************************/
|
|
||||||
code{
|
|
||||||
font-family : "Courier New", Courier, monospace;
|
|
||||||
white-space : pre-wrap;
|
|
||||||
overflow-wrap : break-word;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre code{
|
|
||||||
width : 100%;
|
|
||||||
display : inline-block;
|
|
||||||
}
|
|
||||||
//*****************************
|
|
||||||
// * EXTRAS
|
|
||||||
// *****************************/
|
|
||||||
.columnSplit {
|
|
||||||
visibility : hidden;
|
|
||||||
-webkit-column-break-after : always;
|
|
||||||
break-after : always;
|
|
||||||
-moz-column-break-after : always;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//*****************************
|
//************************************
|
||||||
// * MUSTACHE DIVS/SPANS
|
// * CODE BLOCKS
|
||||||
// *****************************/
|
// ************************************/
|
||||||
.page {
|
code{
|
||||||
.block {
|
font-family : "Courier New", Courier, monospace;
|
||||||
break-inside : avoid;
|
white-space : pre-wrap;
|
||||||
display : inline-block;
|
overflow-wrap : break-word;
|
||||||
width : 100%;
|
|
||||||
}
|
|
||||||
.inline-block {
|
|
||||||
display : inline-block;
|
|
||||||
text-indent : initial;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//*****************************
|
pre code{
|
||||||
// * DEFINITION LISTS
|
width : 100%;
|
||||||
// *****************************/
|
display : inline-block;
|
||||||
.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
|
// * EXTRAS
|
||||||
// *****************************/
|
// *****************************/
|
||||||
.page {
|
.columnSplit {
|
||||||
.blank {
|
visibility : hidden;
|
||||||
height : 1em;
|
-webkit-column-break-after : always;
|
||||||
|
break-after : always;
|
||||||
|
-moz-column-break-after : always;
|
||||||
|
margin-top : 0;
|
||||||
|
& + * {
|
||||||
margin-top : 0;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Watermark */
|
||||||
|
.watermark {
|
||||||
|
display : grid !important;
|
||||||
|
place-items : center;
|
||||||
|
justify-content : center;
|
||||||
|
position : absolute;
|
||||||
|
margin : 0;
|
||||||
|
top : 0;
|
||||||
|
left : 0;
|
||||||
|
width : 100%;
|
||||||
|
height : 100%;
|
||||||
|
font-size : 120px;
|
||||||
|
text-transform : uppercase;
|
||||||
|
color : black;
|
||||||
|
mix-blend-mode : overlay;
|
||||||
|
opacity : 30%;
|
||||||
|
transform : rotate(-45deg);
|
||||||
|
z-index : 500;
|
||||||
|
p {
|
||||||
|
margin-bottom : none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//*****************************
|
/* Watercolor */
|
||||||
// * WIDE
|
[class*="watercolor"] {
|
||||||
// *****************************/
|
position : absolute;
|
||||||
.page {
|
width : 2000px; /* dimensions need to be real big so the user can set */
|
||||||
.wide{
|
height : 2000px; /* height or width and the image will maintain aspect ratio */
|
||||||
column-span : all;
|
-webkit-mask-image : var(--wc);
|
||||||
display : block;
|
-webkit-mask-size : contain;
|
||||||
margin-bottom : 1em;
|
-webkit-mask-repeat : no-repeat;
|
||||||
&+* {
|
mask-image : var(--wc);
|
||||||
margin-top : 0;
|
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));
|
||||||
|
transition : transform 2s;
|
||||||
|
& > 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)));
|
||||||
|
transition : transform 2s;
|
||||||
|
}
|
||||||
|
& img {
|
||||||
|
position : absolute;
|
||||||
|
display : block;
|
||||||
|
bottom : 0;
|
||||||
|
}
|
||||||
|
&.bottom {
|
||||||
|
--rotation : 0;
|
||||||
|
& img {bottom: 0;}
|
||||||
|
}
|
||||||
|
&.top {
|
||||||
|
--rotation : 180;
|
||||||
|
& img {top: 0;}
|
||||||
|
}
|
||||||
|
&.left {
|
||||||
|
--rotation : 90;
|
||||||
|
& img {left: 0;}
|
||||||
|
}
|
||||||
|
&.right {
|
||||||
|
--rotation : -90;
|
||||||
|
& img {right: 0;}
|
||||||
|
}
|
||||||
|
&.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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.imageMaskEdge1 { --wc : url(/assets/waterColorMasks/edge/0001.webp); }
|
||||||
|
.imageMaskEdge2 { --wc : url(/assets/waterColorMasks/edge/0002.webp); }
|
||||||
|
.imageMaskEdge3 { --wc : url(/assets/waterColorMasks/edge/0003.webp); }
|
||||||
|
.imageMaskEdge4 { --wc : url(/assets/waterColorMasks/edge/0004.webp); }
|
||||||
|
.imageMaskEdge5 { --wc : url(/assets/waterColorMasks/edge/0005.webp); }
|
||||||
|
.imageMaskEdge6 { --wc : url(/assets/waterColorMasks/edge/0006.webp); }
|
||||||
|
.imageMaskEdge7 { --wc : url(/assets/waterColorMasks/edge/0007.webp); }
|
||||||
|
.imageMaskEdge8 { --wc : url(/assets/waterColorMasks/edge/0008.webp); }
|
||||||
|
|
||||||
|
[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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.imageMaskCorner1 { --wc : url(/assets/waterColorMasks/corner/0001.webp); }
|
||||||
|
.imageMaskCorner2 { --wc : url(/assets/waterColorMasks/corner/0002.webp); }
|
||||||
|
.imageMaskCorner3 { --wc : url(/assets/waterColorMasks/corner/0003.webp); }
|
||||||
|
.imageMaskCorner4 { --wc : url(/assets/waterColorMasks/corner/0004.webp); }
|
||||||
|
.imageMaskCorner5 { --wc : url(/assets/waterColorMasks/corner/0005.webp); }
|
||||||
|
.imageMaskCorner6 { --wc : url(/assets/waterColorMasks/corner/0006.webp); }
|
||||||
|
.imageMaskCorner7 { --wc : url(/assets/waterColorMasks/corner/0007.webp); }
|
||||||
|
.imageMaskCorner8 { --wc : url(/assets/waterColorMasks/corner/0008.webp); }
|
||||||
|
.imageMaskCorner9 { --wc : url(/assets/waterColorMasks/corner/0009.webp); }
|
||||||
|
.imageMaskCorner10 { --wc : url(/assets/waterColorMasks/corner/0010.webp); }
|
||||||
|
.imageMaskCorner11 { --wc : url(/assets/waterColorMasks/corner/0011.webp); }
|
||||||
|
.imageMaskCorner12 { --wc : url(/assets/waterColorMasks/corner/0012.webp); }
|
||||||
|
.imageMaskCorner13 { --wc : url(/assets/waterColorMasks/corner/0013.webp); }
|
||||||
|
.imageMaskCorner14 { --wc : url(/assets/waterColorMasks/corner/0014.webp); }
|
||||||
|
.imageMaskCorner15 { --wc : url(/assets/waterColorMasks/corner/0015.webp); }
|
||||||
|
.imageMaskCorner16 { --wc : url(/assets/waterColorMasks/corner/0016.webp); }
|
||||||
|
.imageMaskCorner17 { --wc : url(/assets/waterColorMasks/corner/0017.webp); }
|
||||||
|
.imageMaskCorner18 { --wc : url(/assets/waterColorMasks/corner/0018.webp); }
|
||||||
|
.imageMaskCorner19 { --wc : url(/assets/waterColorMasks/corner/0019.webp); }
|
||||||
|
.imageMaskCorner20 { --wc : url(/assets/waterColorMasks/corner/0020.webp); }
|
||||||
|
.imageMaskCorner21 { --wc : url(/assets/waterColorMasks/corner/0021.webp); }
|
||||||
|
.imageMaskCorner22 { --wc : url(/assets/waterColorMasks/corner/0022.webp); }
|
||||||
|
.imageMaskCorner23 { --wc : url(/assets/waterColorMasks/corner/0023.webp); }
|
||||||
|
.imageMaskCorner24 { --wc : url(/assets/waterColorMasks/corner/0024.webp); }
|
||||||
|
.imageMaskCorner25 { --wc : url(/assets/waterColorMasks/corner/0025.webp); }
|
||||||
|
.imageMaskCorner26 { --wc : url(/assets/waterColorMasks/corner/0026.webp); }
|
||||||
|
.imageMaskCorner27 { --wc : url(/assets/waterColorMasks/corner/0027.webp); }
|
||||||
|
.imageMaskCorner28 { --wc : url(/assets/waterColorMasks/corner/0028.webp); }
|
||||||
|
.imageMaskCorner29 { --wc : url(/assets/waterColorMasks/corner/0029.webp); }
|
||||||
|
.imageMaskCorner30 { --wc : url(/assets/waterColorMasks/corner/0030.webp); }
|
||||||
|
.imageMaskCorner31 { --wc : url(/assets/waterColorMasks/corner/0031.webp); }
|
||||||
|
.imageMaskCorner32 { --wc : url(/assets/waterColorMasks/corner/0032.webp); }
|
||||||
|
.imageMaskCorner33 { --wc : url(/assets/waterColorMasks/corner/0033.webp); }
|
||||||
|
.imageMaskCorner34 { --wc : url(/assets/waterColorMasks/corner/0034.webp); }
|
||||||
|
.imageMaskCorner35 { --wc : url(/assets/waterColorMasks/corner/0035.webp); }
|
||||||
|
.imageMaskCorner36 { --wc : url(/assets/waterColorMasks/corner/0036.webp); }
|
||||||
|
.imageMaskCorner37 { --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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//*****************************
|
||||||
|
// * BLANK LINE
|
||||||
|
// *****************************/
|
||||||
|
.page {
|
||||||
|
.blank {
|
||||||
|
height : 1em;
|
||||||
|
margin-top : 0;
|
||||||
|
& + * {
|
||||||
|
margin-top : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//*****************************
|
||||||
|
// * WIDE
|
||||||
|
// *****************************/
|
||||||
|
.page {
|
||||||
|
.wide{
|
||||||
|
column-span : all;
|
||||||
|
display : block;
|
||||||
|
margin-bottom : 1em;
|
||||||
|
&+* {
|
||||||
|
margin-top : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,10 @@
|
|||||||
@monsterBorderImage : url('/assets/monsterBorderFancy.png');
|
@monsterBorderImage : url('/assets/monsterBorderFancy.png');
|
||||||
@codeBorderImage : url('/assets/codeBorder.png');
|
@codeBorderImage : url('/assets/codeBorder.png');
|
||||||
@classTableDecoration : url('/assets/classTableDecoration.png');
|
@classTableDecoration : url('/assets/classTableDecoration.png');
|
||||||
|
@naturalCritLogo : url('/assets/naturalCritLogo.svg');
|
||||||
|
@coverPageBanner : url('/assets/coverPageBanner.svg');
|
||||||
|
@horizontalRule : url('/assets/horizontalRule.svg');
|
||||||
|
@scriptBorder : url('/assets/scriptBorder.png');
|
||||||
|
|
||||||
// Watercolor Images
|
// Watercolor Images
|
||||||
@watercolor1 : url('/assets/watercolor/watercolor1.png');
|
@watercolor1 : url('/assets/watercolor/watercolor1.png');
|
||||||
|
|||||||
1
themes/assets/coverPageBanner.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 970.25 154.67"><defs><style>.cls-1{fill:#ed1f24;}</style></defs><title>Asset 2</title><g id="Layer_2" data-name="Layer 2"><g id="banner"><path id="mainShape" class="cls-1" d="M0,154.67V6.42l188.38,0s137.26,9.45,141.43,9.79c0,.14-96.52,6.76-96.52,6.76l47.09,2.24,39.48-3.05L479.43,34s-36.75,2.68-50.19,3.71c0,.29,178.19,14.48,178.19,14.48s34-3.95,34-4.24c-22.33-1.59-74.72-5.66-74.72-5.66l94-6.19s33.14,2.2,46.39,3.18c12.39.92,40.61,2.82,40.61,2.82l-24.34,2.07,35.24,3,47.36-3.62L762.5,40.26l95-6.94s84.83,6.11,96.45,7c0,.06-65.05,4.32-92.07,6.19-.29,0,39.6,3.57,54.16,4.73,0,.19-108.33,6.75-159.44,10.21,40.47,4.1,86.29,8.6,126,12.62,0,.15-41,4.34-58.14,6.16,0,.21,65.56,5.15,93.67,7.41-.2,0-41.27,2.79-56.81,4,0,.23,44.76,3.66,62.76,5.09,0,.11-103.55,7.17-150.95,10.53,0,.25,47.29,3.67,66.36,5.19,0,.1-62.19,4.45-89.84,6.47,0,.27,10.77,2.61,10.77,2.61L532.16,139.22,459.29,134l44.38-3.57L434.1,125l-58.43,4.31,59.76,4.36-123.38,11,44.19,3.14S337.9,149.34,330,150c-9.83.77-59.3,4.72-59.3,4.72Z"/><polygon id="diamondF" class="cls-1" points="552.6 154.33 469.43 147.19 550.72 142.21 633.24 148.52 552.6 154.33"/><polygon id="diamondE" class="cls-1" points="631.14 140.38 741.62 130.66 782.71 133.62 755.63 135.82 812.67 140.14 722.1 146.81 631.14 140.38"/><polygon id="diamondD" class="cls-1" points="812.57 62.87 892.92 57.13 970.25 63.1 894.05 68.76 812.57 62.87"/><path id="diamondC" class="cls-1" d="M480.21,29.59c4.21-.38,71.22-4.68,71.22-4.68l67.15,4.94-68.22,4.87S480.22,29.68,480.21,29.59Z"/><polygon id="diamondB" class="cls-1" points="450.19 23.52 344.58 16.3 449.17 8.62 556.38 16.36 450.19 23.52"/><polygon id="diamondA" class="cls-1" points="297.87 0 350.13 3.9 296.54 7.79 241.43 3.9 297.87 0"/></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
BIN
themes/assets/dragonBackground.png
Normal file
|
After Width: | Height: | Size: 366 KiB |
1
themes/assets/horizontalRule.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 762.29 18.4"><defs><style>.cls-1{fill:#ed1f24;}</style></defs><title>Asset 2</title><g id="Layer_2" data-name="Layer 2"><g id="horizontalRule"><path id="mainShape" class="cls-1" d="M0,9.06S406.1,0,381.53,0,762.29,8.7,762.29,8.7s-350.49,10-381.53,9.69S0,9.06,0,9.06Z"/></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 335 B |
1
themes/assets/naturalCritLogo.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 94.65 94.6"><defs><style>.cls-1{fill:#ed1f24;}</style></defs><title>NaturalCritLogo</title><g id="Layer_2" data-name="Layer 2"><g id="base"><path id="D20" class="cls-1" d="M63.45.09s-45.91,12.4-46,12.45a.71.71,0,0,0-.15.08l-.15.1-.12.11a1.07,1.07,0,0,0-.14.16l-.09.11-.12.23,0,.06L.2,54.9a1.59,1.59,0,0,0,.11,1.69L29.36,94h0l0,0,.08.08.08.08.09.09.08.06.13.07a0,0,0,0,0,0,0,1.59,1.59,0,0,0,.27.12l.13.05.06,0a1.55,1.55,0,0,0,.37,0,1.63,1.63,0,0,0,.31,0l45.67-8.3.16,0,.11,0,.12,0,.06,0s0,0,0,0l.06,0a1.65,1.65,0,0,0,.36-.28l0-.06a1.6,1.6,0,0,0,.26-.38s0,0,0,0v0h0a.14.14,0,0,1,0-.06L94.52,43.74a1.4,1.4,0,0,0,.11-.4.41.41,0,0,0,0-.11,1.13,1.13,0,0,0,0-.26.66.66,0,0,0,0-.14,2,2,0,0,0-.06-.26l0-.11a2.68,2.68,0,0,0-.18-.33v0L65.29.6C64.77-.31,63.45.09,63.45.09ZM74.9,81.7l-28.81-18L78.5,38.49ZM44.1,61l-11-40.17L77,35.39ZM82,37.78l8.92,5.95L79,73.48Zm4.46-1.1-4.6-3.06L75.69,21.36Zm-9.26-4.8-42.07-14,28.05-14ZM30.56,16.34l-6.49-2.16L47.85,7.7Zm-11.35-.21L27.88,19,7.64,45Zm10.73,5.76L40.78,61.64,4.64,54.42Zm10.82,43.2L30.26,89.6,5.75,58.09Zm3.16,1.24L71.74,83.72l-38.26,7Z"/></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
BIN
themes/assets/scriptBorder.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
themes/assets/waterColorMasks/corner/0001.webp
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
themes/assets/waterColorMasks/corner/0002.webp
Normal file
|
After Width: | Height: | Size: 143 KiB |
BIN
themes/assets/waterColorMasks/corner/0003.webp
Normal file
|
After Width: | Height: | Size: 105 KiB |
BIN
themes/assets/waterColorMasks/corner/0004.webp
Normal file
|
After Width: | Height: | Size: 177 KiB |
BIN
themes/assets/waterColorMasks/corner/0005.webp
Normal file
|
After Width: | Height: | Size: 141 KiB |
BIN
themes/assets/waterColorMasks/corner/0006.webp
Normal file
|
After Width: | Height: | Size: 138 KiB |
BIN
themes/assets/waterColorMasks/corner/0007.webp
Normal file
|
After Width: | Height: | Size: 135 KiB |
BIN
themes/assets/waterColorMasks/corner/0008.webp
Normal file
|
After Width: | Height: | Size: 101 KiB |
BIN
themes/assets/waterColorMasks/corner/0009.webp
Normal file
|
After Width: | Height: | Size: 132 KiB |
BIN
themes/assets/waterColorMasks/corner/0010.webp
Normal file
|
After Width: | Height: | Size: 140 KiB |
BIN
themes/assets/waterColorMasks/corner/0011.webp
Normal file
|
After Width: | Height: | Size: 206 KiB |
BIN
themes/assets/waterColorMasks/corner/0012.webp
Normal file
|
After Width: | Height: | Size: 236 KiB |
BIN
themes/assets/waterColorMasks/corner/0013.webp
Normal file
|
After Width: | Height: | Size: 212 KiB |
BIN
themes/assets/waterColorMasks/corner/0014.webp
Normal file
|
After Width: | Height: | Size: 285 KiB |
BIN
themes/assets/waterColorMasks/corner/0015.webp
Normal file
|
After Width: | Height: | Size: 114 KiB |
BIN
themes/assets/waterColorMasks/corner/0016.webp
Normal file
|
After Width: | Height: | Size: 105 KiB |
BIN
themes/assets/waterColorMasks/corner/0017.webp
Normal file
|
After Width: | Height: | Size: 168 KiB |
BIN
themes/assets/waterColorMasks/corner/0018.webp
Normal file
|
After Width: | Height: | Size: 326 KiB |
BIN
themes/assets/waterColorMasks/corner/0019.webp
Normal file
|
After Width: | Height: | Size: 156 KiB |
BIN
themes/assets/waterColorMasks/corner/0020.webp
Normal file
|
After Width: | Height: | Size: 147 KiB |
BIN
themes/assets/waterColorMasks/corner/0021.webp
Normal file
|
After Width: | Height: | Size: 140 KiB |
BIN
themes/assets/waterColorMasks/corner/0022.webp
Normal file
|
After Width: | Height: | Size: 334 KiB |
BIN
themes/assets/waterColorMasks/corner/0023.webp
Normal file
|
After Width: | Height: | Size: 154 KiB |
BIN
themes/assets/waterColorMasks/corner/0024.webp
Normal file
|
After Width: | Height: | Size: 290 KiB |
BIN
themes/assets/waterColorMasks/corner/0025.webp
Normal file
|
After Width: | Height: | Size: 174 KiB |
BIN
themes/assets/waterColorMasks/corner/0026.webp
Normal file
|
After Width: | Height: | Size: 265 KiB |
BIN
themes/assets/waterColorMasks/corner/0027.webp
Normal file
|
After Width: | Height: | Size: 140 KiB |
BIN
themes/assets/waterColorMasks/corner/0028.webp
Normal file
|
After Width: | Height: | Size: 319 KiB |
BIN
themes/assets/waterColorMasks/corner/0029.webp
Normal file
|
After Width: | Height: | Size: 216 KiB |