mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2025-12-30 19:42:43 +00:00
Merge branch 'master' into createUIBasePage
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -11,3 +11,4 @@ config/docker.*
|
|||||||
todo.md
|
todo.md
|
||||||
startDB.bat
|
startDB.bat
|
||||||
startMViewer.bat
|
startMViewer.bat
|
||||||
|
.vscode
|
||||||
|
|||||||
81
changelog.md
81
changelog.md
@@ -1,6 +1,7 @@
|
|||||||
```css
|
```css
|
||||||
h5 {
|
h5 {
|
||||||
font-size: .35cm !important;
|
font-size: .35cm !important;
|
||||||
|
margin-top: 0.3cm;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page ul ul {
|
.page ul ul {
|
||||||
@@ -14,6 +15,11 @@ h5 {
|
|||||||
filter: brightness(1.1) drop-shadow(1px 2px 1px #222);
|
filter: brightness(1.1) drop-shadow(1px 2px 1px #222);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.taskList ul {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
.taskList li input[checked] {
|
.taskList li input[checked] {
|
||||||
filter: sepia(100%) hue-rotate(60deg) saturate(3.5) contrast(4) brightness(1.1) drop-shadow(1px 2px 1px #222);
|
filter: sepia(100%) hue-rotate(60deg) saturate(3.5) contrast(4) brightness(1.1) drop-shadow(1px 2px 1px #222);
|
||||||
}
|
}
|
||||||
@@ -39,6 +45,81 @@ 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).
|
||||||
|
|
||||||
|
### Thursday 28/10/2022 - v3.3.1
|
||||||
|
{{taskList
|
||||||
|
|
||||||
|
##### Calculuschild
|
||||||
|
|
||||||
|
* [x] Fixes to several broken CSS styles from v3.3.0
|
||||||
|
|
||||||
|
Fixes issues [#2468](https://github.com/naturalcrit/homebrewery/issues/2468)
|
||||||
|
|
||||||
|
##### Jeddai
|
||||||
|
|
||||||
|
* [x] Reduce size of thumbnails on social media links
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
### Friday 19/10/2022 - v3.3.0
|
||||||
|
{{taskList
|
||||||
|
|
||||||
|
##### Calculuschild
|
||||||
|
|
||||||
|
* [x] Fix for tables broken by Chrome v106
|
||||||
|
|
||||||
|
|
||||||
|
##### G-Ambatte:
|
||||||
|
|
||||||
|
* [x] Fix Table of Contents broken by Chrome v106
|
||||||
|
|
||||||
|
Fixes issues [#2437](https://github.com/naturalcrit/homebrewery/issues/2437)
|
||||||
|
|
||||||
|
* [x] Show brew thumbnails on user page
|
||||||
|
|
||||||
|
Fixes issues [#2331](https://github.com/naturalcrit/homebrewery/issues/2331)
|
||||||
|
|
||||||
|
* [x] Allow longer URLs for brew thumbnails
|
||||||
|
|
||||||
|
Fixes issues [#2351](https://github.com/naturalcrit/homebrewery/issues/2351)
|
||||||
|
|
||||||
|
* [x] Code no longer unfolds when inserting a snippet
|
||||||
|
|
||||||
|
Fixes issues [#2135](https://github.com/naturalcrit/homebrewery/issues/2135)
|
||||||
|
|
||||||
|
* [x] Fix brew settings being lost on first save
|
||||||
|
|
||||||
|
Fixes issues [#2427](https://github.com/naturalcrit/homebrewery/issues/2427)
|
||||||
|
|
||||||
|
|
||||||
|
##### Gazook:
|
||||||
|
|
||||||
|
* [x] Several updates to bug reporting and error popups
|
||||||
|
|
||||||
|
Fixes issues [#2376](https://github.com/naturalcrit/homebrewery/issues/2376)
|
||||||
|
|
||||||
|
* [x] Fixes to userpage search bar
|
||||||
|
|
||||||
|
Fixes issues [#1675](https://github.com/naturalcrit/homebrewery/issues/1675), [#2353](https://github.com/naturalcrit/homebrewery/issues/2353)
|
||||||
|
|
||||||
|
* [x] Renderer *(legacy / V3)* now shown next to page #
|
||||||
|
|
||||||
|
Fixes issues [#1928](https://github.com/naturalcrit/homebrewery/issues/1928)
|
||||||
|
|
||||||
|
* [x] Prevent text selection when moving divider bar
|
||||||
|
|
||||||
|
Fixes issues [#1632](https://github.com/naturalcrit/homebrewery/issues/1632)
|
||||||
|
|
||||||
|
* [x] Tweak Monster Stat Block coloring
|
||||||
|
|
||||||
|
Fixes issues [#2123](https://github.com/naturalcrit/homebrewery/issues/2123)
|
||||||
|
|
||||||
|
* [x] Added dropdown button to toggle autosave
|
||||||
|
|
||||||
|
Fixes issues [#1546](https://github.com/naturalcrit/homebrewery/issues/1546)
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
### Friday 08/09/2022 - v3.2.2
|
### Friday 08/09/2022 - v3.2.2
|
||||||
{{taskList
|
{{taskList
|
||||||
|
|
||||||
|
|||||||
@@ -19,11 +19,6 @@ const DEFAULT_STYLE_TEXT = dedent`
|
|||||||
color: black;
|
color: black;
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
const splice = function(str, index, inject){
|
|
||||||
return str.slice(0, index) + inject + str.slice(index);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Editor = createClass({
|
const Editor = createClass({
|
||||||
displayName : 'Editor',
|
displayName : 'Editor',
|
||||||
@@ -80,19 +75,7 @@ const Editor = createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
handleInject : function(injectText){
|
handleInject : function(injectText){
|
||||||
let text;
|
this.refs.codeEditor?.injectText(injectText, false);
|
||||||
if(this.isText()) text = this.props.brew.text;
|
|
||||||
if(this.isStyle()) text = this.props.brew.style ?? DEFAULT_STYLE_TEXT;
|
|
||||||
|
|
||||||
const lines = text.split('\n');
|
|
||||||
const cursorPos = this.refs.codeEditor.getCursorPosition();
|
|
||||||
lines[cursorPos.line] = splice(lines[cursorPos.line], cursorPos.ch, injectText);
|
|
||||||
|
|
||||||
const injectLines = injectText.split('\n');
|
|
||||||
this.refs.codeEditor.setCursorPosition(cursorPos.line + injectLines.length, cursorPos.ch + injectLines[injectLines.length - 1].length);
|
|
||||||
|
|
||||||
if(this.isText()) this.props.onTextChange(lines.join('\n'));
|
|
||||||
if(this.isStyle()) this.props.onStyleChange(lines.join('\n'));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleViewChange : function(newView){
|
handleViewChange : function(newView){
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ const Account = createClass({
|
|||||||
{global.account.username}
|
{global.account.username}
|
||||||
</Nav.item>
|
</Nav.item>
|
||||||
<Nav.item
|
<Nav.item
|
||||||
href={`/user/${global.account.username}`}
|
href={`/user/${encodeURI(global.account.username)}`}
|
||||||
color='yellow'
|
color='yellow'
|
||||||
icon='fas fa-beer'
|
icon='fas fa-beer'
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -55,6 +55,18 @@
|
|||||||
text-align : center;
|
text-align : center;
|
||||||
text-transform : initial;
|
text-transform : initial;
|
||||||
}
|
}
|
||||||
|
.save-menu {
|
||||||
|
.dropdown {
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
.navItem i.fa-power-off {
|
||||||
|
color : red;
|
||||||
|
&.active {
|
||||||
|
color : rgb(0, 182, 52);
|
||||||
|
filter : drop-shadow(0 0 2px rgba(0, 182, 52, 0.765))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.patreon.navItem{
|
.patreon.navItem{
|
||||||
border-left : 1px solid #666;
|
border-left : 1px solid #666;
|
||||||
border-right : 1px solid #666;
|
border-right : 1px solid #666;
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ const BrewItem = createClass({
|
|||||||
<i className='fas fa-tags'/>
|
<i className='fas fa-tags'/>
|
||||||
{brew.tags.map((tag, idx)=>{
|
{brew.tags.map((tag, idx)=>{
|
||||||
const matches = tag.match(/^(?:([^:]+):)?([^:]+)$/);
|
const matches = tag.match(/^(?:([^:]+):)?([^:]+)$/);
|
||||||
return <span className={matches[1]}>{matches[2]}</span>;
|
return <span key={idx} className={matches[1]}>{matches[2]}</span>;
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</> : <></>
|
</> : <></>
|
||||||
|
|||||||
@@ -26,7 +26,29 @@
|
|||||||
font-size : 1.3em;
|
font-size : 1.3em;
|
||||||
font-style : italic;
|
font-style : italic;
|
||||||
}
|
}
|
||||||
|
.brewCollection {
|
||||||
|
h1:hover{
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.active::before, .inactive::before {
|
||||||
|
font-family: 'Font Awesome 5 Free';
|
||||||
|
font-weight: 900;
|
||||||
|
font-size: 0.6cm;
|
||||||
|
padding-right: 0.5em;
|
||||||
|
}
|
||||||
|
.active {
|
||||||
|
color: var(--HB_Color_HeaderText);
|
||||||
|
}
|
||||||
|
.active::before {
|
||||||
|
content: '\f107';
|
||||||
|
}
|
||||||
|
.inactive {
|
||||||
|
color: #707070;
|
||||||
|
}
|
||||||
|
.inactive::before {
|
||||||
|
content: '\f105';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.sort-container{
|
.sort-container{
|
||||||
|
|||||||
@@ -62,7 +62,10 @@ const EditPage = createClass({
|
|||||||
confirmGoogleTransfer : false,
|
confirmGoogleTransfer : false,
|
||||||
errors : null,
|
errors : null,
|
||||||
htmlErrors : Markdown.validate(this.props.brew.text),
|
htmlErrors : Markdown.validate(this.props.brew.text),
|
||||||
url : ''
|
url : '',
|
||||||
|
autoSave : true,
|
||||||
|
autoSaveWarning : false,
|
||||||
|
unsavedTime : new Date()
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
savedBrew : null,
|
savedBrew : null,
|
||||||
@@ -72,9 +75,17 @@ const EditPage = createClass({
|
|||||||
url : window.location.href
|
url : window.location.href
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
this.savedBrew = JSON.parse(JSON.stringify(this.props.brew)); //Deep copy
|
this.savedBrew = JSON.parse(JSON.stringify(this.props.brew)); //Deep copy
|
||||||
|
|
||||||
this.trySave();
|
this.setState({ autoSave: JSON.parse(localStorage.getItem('AUTOSAVE_ON')) ?? true }, ()=>{
|
||||||
|
if(this.state.autoSave){
|
||||||
|
this.trySave();
|
||||||
|
} else {
|
||||||
|
this.setState({ autoSaveWarning: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
window.onbeforeunload = ()=>{
|
window.onbeforeunload = ()=>{
|
||||||
if(this.state.isSaving || this.state.isPending){
|
if(this.state.isSaving || this.state.isPending){
|
||||||
return 'You have unsaved changes!';
|
return 'You have unsaved changes!';
|
||||||
@@ -117,14 +128,14 @@ const EditPage = createClass({
|
|||||||
brew : { ...prevState.brew, text: text },
|
brew : { ...prevState.brew, text: text },
|
||||||
isPending : true,
|
isPending : true,
|
||||||
htmlErrors : htmlErrors
|
htmlErrors : htmlErrors
|
||||||
}), ()=>this.trySave());
|
}), ()=>{if(this.state.autoSave) this.trySave();});
|
||||||
},
|
},
|
||||||
|
|
||||||
handleStyleChange : function(style){
|
handleStyleChange : function(style){
|
||||||
this.setState((prevState)=>({
|
this.setState((prevState)=>({
|
||||||
brew : { ...prevState.brew, style: style },
|
brew : { ...prevState.brew, style: style },
|
||||||
isPending : true
|
isPending : true
|
||||||
}), ()=>this.trySave());
|
}), ()=>{if(this.state.autoSave) this.trySave();});
|
||||||
},
|
},
|
||||||
|
|
||||||
handleMetaChange : function(metadata){
|
handleMetaChange : function(metadata){
|
||||||
@@ -134,7 +145,7 @@ const EditPage = createClass({
|
|||||||
...metadata
|
...metadata
|
||||||
},
|
},
|
||||||
isPending : true,
|
isPending : true,
|
||||||
}), ()=>this.trySave());
|
}), ()=>{if(this.state.autoSave) this.trySave();});
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -221,8 +232,9 @@ const EditPage = createClass({
|
|||||||
editId : this.savedBrew.editId,
|
editId : this.savedBrew.editId,
|
||||||
shareId : this.savedBrew.shareId
|
shareId : this.savedBrew.shareId
|
||||||
},
|
},
|
||||||
isPending : false,
|
isPending : false,
|
||||||
isSaving : false,
|
isSaving : false,
|
||||||
|
unsavedTime : new Date()
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -329,17 +341,55 @@ const EditPage = createClass({
|
|||||||
</Nav.item>;
|
</Nav.item>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(this.state.autoSaveWarning && this.hasChanges()){
|
||||||
|
this.setAutosaveWarning();
|
||||||
|
const elapsedTime = Math.round((new Date() - this.state.unsavedTime) / 1000 / 60);
|
||||||
|
const text = elapsedTime == 0 ? 'Autosave is OFF.' : `Autosave is OFF, and you haven't saved for ${elapsedTime} minutes.`;
|
||||||
|
|
||||||
|
return <Nav.item className='save error' icon='fas fa-exclamation-circle'>
|
||||||
|
Reminder...
|
||||||
|
<div className='errorContainer'>
|
||||||
|
{text}
|
||||||
|
</div>
|
||||||
|
</Nav.item>;
|
||||||
|
}
|
||||||
|
|
||||||
if(this.state.isSaving){
|
if(this.state.isSaving){
|
||||||
return <Nav.item className='save' icon='fas fa-spinner fa-spin'>saving...</Nav.item>;
|
return <Nav.item className='save' icon='fas fa-spinner fa-spin'>saving...</Nav.item>;
|
||||||
}
|
}
|
||||||
if(this.state.isPending && this.hasChanges()){
|
if(this.state.isPending && this.hasChanges()){
|
||||||
return <Nav.item className='save' onClick={this.save} color='blue' icon='fas fa-save'>Save Now</Nav.item>;
|
return <Nav.item className='save' onClick={this.save} color='blue' icon='fas fa-save'>Save Now</Nav.item>;
|
||||||
}
|
}
|
||||||
|
if(!this.state.isPending && !this.state.isSaving && this.state.autoSave){
|
||||||
|
return <Nav.item className='save saved'>auto-saved.</Nav.item>;
|
||||||
|
}
|
||||||
if(!this.state.isPending && !this.state.isSaving){
|
if(!this.state.isPending && !this.state.isSaving){
|
||||||
return <Nav.item className='save saved'>saved.</Nav.item>;
|
return <Nav.item className='save saved'>saved.</Nav.item>;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handleAutoSave : function(){
|
||||||
|
if(this.warningTimer) clearTimeout(this.warningTimer);
|
||||||
|
this.setState((prevState)=>({
|
||||||
|
autoSave : !prevState.autoSave,
|
||||||
|
autoSaveWarning : prevState.autoSave
|
||||||
|
}), ()=>{
|
||||||
|
localStorage.setItem('AUTOSAVE_ON', JSON.stringify(this.state.autoSave));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setAutosaveWarning : function(){
|
||||||
|
setTimeout(()=>this.setState({ autoSaveWarning: false }), 4000); // 4 seconds to display
|
||||||
|
this.warningTimer = setTimeout(()=>{this.setState({ autoSaveWarning: true });}, 900000); // 15 minutes between warnings
|
||||||
|
this.warningTimer;
|
||||||
|
},
|
||||||
|
|
||||||
|
renderAutoSaveButton : function(){
|
||||||
|
return <Nav.item onClick={this.handleAutoSave}>
|
||||||
|
Autosave <i className={this.state.autoSave ? 'fas fa-power-off active' : 'fas fa-power-off'}></i>
|
||||||
|
</Nav.item>;
|
||||||
|
},
|
||||||
|
|
||||||
processShareId : function() {
|
processShareId : function() {
|
||||||
return this.state.brew.googleId && !this.state.brew.stubbed ?
|
return this.state.brew.googleId && !this.state.brew.stubbed ?
|
||||||
this.state.brew.googleId + this.state.brew.shareId :
|
this.state.brew.googleId + this.state.brew.shareId :
|
||||||
@@ -378,7 +428,10 @@ const EditPage = createClass({
|
|||||||
|
|
||||||
<Nav.section>
|
<Nav.section>
|
||||||
{this.renderGoogleDriveIcon()}
|
{this.renderGoogleDriveIcon()}
|
||||||
{this.renderSaveButton()}
|
<Nav.dropdown className='save-menu'>
|
||||||
|
{this.renderSaveButton()}
|
||||||
|
{this.renderAutoSaveButton()}
|
||||||
|
</Nav.dropdown>
|
||||||
<NewBrew />
|
<NewBrew />
|
||||||
<HelpNavItem/>
|
<HelpNavItem/>
|
||||||
<Nav.dropdown>
|
<Nav.dropdown>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
position : absolute;
|
position : absolute;
|
||||||
top : 100%;
|
top : 100%;
|
||||||
left : 50%;
|
left : 50%;
|
||||||
z-index : 100000;
|
z-index : 500;
|
||||||
width : 140px;
|
width : 140px;
|
||||||
padding : 3px;
|
padding : 3px;
|
||||||
color : white;
|
color : white;
|
||||||
|
|||||||
@@ -38,9 +38,7 @@ const HomePage = createClass({
|
|||||||
},
|
},
|
||||||
handleSave : function(){
|
handleSave : function(){
|
||||||
request.post('/api')
|
request.post('/api')
|
||||||
.send({
|
.send(this.state.brew)
|
||||||
text : this.state.brew.text
|
|
||||||
})
|
|
||||||
.end((err, res)=>{
|
.end((err, res)=>{
|
||||||
if(err) return;
|
if(err) return;
|
||||||
const brew = res.body;
|
const brew = res.body;
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ const PrintPage = createClass({
|
|||||||
|
|
||||||
return <div>
|
return <div>
|
||||||
<Meta name='robots' content='noindex, nofollow' />
|
<Meta name='robots' content='noindex, nofollow' />
|
||||||
|
<link href={`/themes/${rendererPath}/Blank/style.css`} rel='stylesheet'/>
|
||||||
{baseThemePath &&
|
{baseThemePath &&
|
||||||
<link href={`/themes/${rendererPath}/${baseThemePath}/style.css`} rel='stylesheet'/>
|
<link href={`/themes/${rendererPath}/${baseThemePath}/style.css`} rel='stylesheet'/>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ module.exports = async(name, title = '', props = {})=>{
|
|||||||
<meta property="og:description" content="${props.brew?.description || 'No description.'}">
|
<meta property="og:description" content="${props.brew?.description || 'No description.'}">
|
||||||
<meta property="og:site_name" content="The Homebrewery - Make your Homebrew content look legit!">
|
<meta property="og:site_name" content="The Homebrewery - Make your Homebrew content look legit!">
|
||||||
<meta property="og:type" content="article">
|
<meta property="og:type" content="article">
|
||||||
<meta name="twitter:card" content="summary_large_image">
|
<meta name="twitter:card" content="summary">
|
||||||
<title>${title.length ? `${title} - The Homebrewery`: 'The Homebrewery - NaturalCrit'}</title>
|
<title>${title.length ? `${title} - The Homebrewery`: 'The Homebrewery - NaturalCrit'}</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
6595
package-lock.json
generated
6595
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
30
package.json
30
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.2.2",
|
"version": "3.3.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "16.11.x"
|
"node": "16.11.x"
|
||||||
},
|
},
|
||||||
@@ -51,44 +51,44 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "^7.19.1",
|
"@babel/core": "^7.19.6",
|
||||||
"@babel/plugin-transform-runtime": "^7.19.1",
|
"@babel/plugin-transform-runtime": "^7.19.6",
|
||||||
"@babel/preset-env": "^7.19.1",
|
"@babel/preset-env": "^7.19.4",
|
||||||
"@babel/preset-react": "^7.18.6",
|
"@babel/preset-react": "^7.18.6",
|
||||||
"body-parser": "^1.20.0",
|
"body-parser": "^1.20.1",
|
||||||
"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",
|
||||||
"create-react-class": "^15.7.0",
|
"create-react-class": "^15.7.0",
|
||||||
"dedent-tabs": "^0.10.1",
|
"dedent-tabs": "^0.10.2",
|
||||||
"express": "^4.18.1",
|
"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": "10.1.0",
|
"fs-extra": "10.1.0",
|
||||||
"googleapis": "108.0.0",
|
"googleapis": "108.0.1",
|
||||||
"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.1.0",
|
"marked": "4.1.1",
|
||||||
"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.6.1",
|
"mongoose": "^6.7.0",
|
||||||
"nanoid": "3.3.4",
|
"nanoid": "3.3.4",
|
||||||
"nconf": "^0.12.0",
|
"nconf": "^0.12.0",
|
||||||
"react": "^16.14.0",
|
"react": "^16.14.0",
|
||||||
"react-dom": "^16.14.0",
|
"react-dom": "^16.14.0",
|
||||||
"react-frame-component": "4.1.3",
|
"react-frame-component": "4.1.3",
|
||||||
"react-router-dom": "6.3.0",
|
"react-router-dom": "6.4.2",
|
||||||
"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.24.0",
|
"eslint": "^8.26.0",
|
||||||
"eslint-plugin-react": "^7.31.8",
|
"eslint-plugin-react": "^7.31.10",
|
||||||
"jest": "^29.0.3",
|
"jest": "^29.2.2",
|
||||||
"supertest": "^6.2.4"
|
"supertest": "^6.3.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -229,6 +229,15 @@ const CodeEditor = createClass({
|
|||||||
this.codeMirror.replaceSelection('\n\\page\n\n', 'end');
|
this.codeMirror.replaceSelection('\n\\page\n\n', 'end');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
injectText : function(injectText, overwrite=true) {
|
||||||
|
const cm = this.codeMirror;
|
||||||
|
if(!overwrite) {
|
||||||
|
cm.setCursor(cm.getCursor('from'));
|
||||||
|
}
|
||||||
|
cm.replaceSelection(injectText, 'end');
|
||||||
|
cm.focus();
|
||||||
|
},
|
||||||
|
|
||||||
makeUnderline : function() {
|
makeUnderline : function() {
|
||||||
const selection = this.codeMirror.getSelection(), t = selection.slice(0, 3) === '<u>' && selection.slice(-4) === '</u>';
|
const selection = this.codeMirror.getSelection(), t = selection.slice(0, 3) === '<u>' && selection.slice(-4) === '</u>';
|
||||||
this.codeMirror.replaceSelection(t ? selection.slice(3, -4) : `<u>${selection}</u>`, 'around');
|
this.codeMirror.replaceSelection(t ? selection.slice(3, -4) : `<u>${selection}</u>`, 'around');
|
||||||
|
|||||||
@@ -77,9 +77,12 @@ body {
|
|||||||
text-rendering : optimizeLegibility;
|
text-rendering : optimizeLegibility;
|
||||||
page-break-before : always;
|
page-break-before : always;
|
||||||
page-break-after : always;
|
page-break-after : always;
|
||||||
|
}
|
||||||
//*****************************
|
//*****************************
|
||||||
// * BASE
|
// * BASE
|
||||||
// *****************************/
|
// *****************************/
|
||||||
|
|
||||||
|
.page{
|
||||||
p{
|
p{
|
||||||
overflow-wrap : break-word; //TODO: MAKE ALL MARGINS TOP-ONLY. USE * + * STYLE SELECTORS
|
overflow-wrap : break-word; //TODO: MAKE ALL MARGINS TOP-ONLY. USE * + * STYLE SELECTORS
|
||||||
display : block;
|
display : block;
|
||||||
@@ -155,9 +158,9 @@ body {
|
|||||||
padding-bottom : 2px;
|
padding-bottom : 2px;
|
||||||
margin-bottom : -20px;
|
margin-bottom : -20px;
|
||||||
background-image : linear-gradient(-45deg, #322814, #998250, #322814);
|
background-image : linear-gradient(-45deg, #322814, #998250, #322814);
|
||||||
background-clip : text;
|
background-clip : text;
|
||||||
-webkit-background-clip : text;
|
-webkit-background-clip : text;
|
||||||
color : rgba(0, 0, 0, 0);
|
color : rgba(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
&+p::first-line{
|
&+p::first-line{
|
||||||
font-variant : small-caps;
|
font-variant : small-caps;
|
||||||
@@ -175,12 +178,24 @@ body {
|
|||||||
font-size : 0.575cm;
|
font-size : 0.575cm;
|
||||||
border-bottom : 2px solid var(--HB_Color_HeaderUnderline);;
|
border-bottom : 2px solid var(--HB_Color_HeaderUnderline);;
|
||||||
line-height : 0.995em; //Font is misaligned. Shift up slightly
|
line-height : 0.995em; //Font is misaligned. Shift up slightly
|
||||||
|
& + * {
|
||||||
|
margin-top: 0.17cm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
* + h3 {
|
||||||
|
margin-top : 0.155cm; //(0.325 - 0.17)
|
||||||
}
|
}
|
||||||
h4{
|
h4{
|
||||||
//margin-top : -0.02cm; //Font is misaligned. Shift up slightly
|
//margin-top : -0.02cm; //Font is misaligned. Shift up slightly
|
||||||
//margin-bottom : 0.02cm;
|
//margin-bottom : 0.02cm;
|
||||||
font-size : 0.458cm;
|
font-size : 0.458cm;
|
||||||
line-height : 0.971em; //Font is misaligned. Shift up slightly
|
line-height : 0.971em; //Font is misaligned. Shift up slightly
|
||||||
|
& + * {
|
||||||
|
margin-top: 0.09cm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
* + h4 {
|
||||||
|
margin-top : 0.235cm; //(0.325 - 0.09)
|
||||||
}
|
}
|
||||||
h5{
|
h5{
|
||||||
//margin-top : -0.02cm; //Font is misaligned. Shift up slightly
|
//margin-top : -0.02cm; //Font is misaligned. Shift up slightly
|
||||||
@@ -199,6 +214,7 @@ body {
|
|||||||
table{
|
table{
|
||||||
.useSansSerif();
|
.useSansSerif();
|
||||||
width : 100%;
|
width : 100%;
|
||||||
|
line-height : 16px;
|
||||||
& + * {
|
& + * {
|
||||||
margin-top : 0.325cm;
|
margin-top : 0.325cm;
|
||||||
}
|
}
|
||||||
@@ -207,13 +223,17 @@ body {
|
|||||||
font-weight : 800;
|
font-weight : 800;
|
||||||
th{
|
th{
|
||||||
vertical-align : bottom;
|
vertical-align : bottom;
|
||||||
padding : 0.14em 0.4em;
|
//padding : 0.14em 0.4em;
|
||||||
|
padding : 0px 1.5px; // Both of these are temporary, just to force
|
||||||
|
//line-height : 16px; // PDF to render at same height until Chrome 108
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tbody{
|
tbody{
|
||||||
tr{
|
tr{
|
||||||
td{
|
td{
|
||||||
padding : 0.14em 0.4em;
|
//padding : 0.14em 0.4em;
|
||||||
|
padding : 0px 1.5px; // Both of these are temporary, just to force
|
||||||
|
//line-height : 16px; // PDF to render at same height until Chrome 108
|
||||||
}
|
}
|
||||||
&:nth-child(odd){
|
&:nth-child(odd){
|
||||||
background-color : var(--HB_Color_Accent);
|
background-color : var(--HB_Color_Accent);
|
||||||
@@ -625,6 +645,9 @@ body {
|
|||||||
&.wide:first-child {
|
&.wide:first-child {
|
||||||
margin-top: 0.12cm;
|
margin-top: 0.12cm;
|
||||||
}
|
}
|
||||||
|
& + * {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&.decoration {
|
&.decoration {
|
||||||
position:relative;
|
position:relative;
|
||||||
@@ -657,90 +680,78 @@ body {
|
|||||||
//*****************************
|
//*****************************
|
||||||
// * TABLE OF CONTENTS
|
// * TABLE OF CONTENTS
|
||||||
// *****************************/
|
// *****************************/
|
||||||
.page .toc{
|
.page {
|
||||||
|
&:has(.toc):after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.toc {
|
||||||
-webkit-column-break-inside : avoid;
|
-webkit-column-break-inside : avoid;
|
||||||
page-break-inside : avoid;
|
page-break-inside : avoid;
|
||||||
break-inside : avoid;
|
break-inside : avoid;
|
||||||
h1 {
|
h1 {
|
||||||
text-align : center;
|
text-align : center;
|
||||||
margin-bottom : 0.3cm;
|
margin-bottom : 0.3cm;
|
||||||
}
|
|
||||||
a{
|
|
||||||
display : inline;
|
|
||||||
color : inherit;
|
|
||||||
text-decoration : none;
|
|
||||||
&:hover{
|
|
||||||
text-decoration : underline;
|
|
||||||
}
|
}
|
||||||
}
|
a{
|
||||||
h4 {
|
display : inline;
|
||||||
margin-top : 0.2cm;
|
color : inherit;
|
||||||
line-height : 0.4cm;
|
text-decoration : none;
|
||||||
& + ul li {
|
&:hover{
|
||||||
line-height: 1.2em;
|
text-decoration : underline;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
h4 {
|
||||||
ul{
|
margin-top : 0.2cm;
|
||||||
padding-left : 0;
|
line-height : 0.4cm;
|
||||||
list-style-type : none;
|
& + ul li {
|
||||||
li + li h3 {
|
line-height: 1.2em;
|
||||||
margin-top : 0.26cm;
|
}
|
||||||
line-height : 1em
|
|
||||||
}
|
}
|
||||||
h3 span:first-child::after {
|
ul{
|
||||||
border : none;
|
padding-left : 0;
|
||||||
}
|
list-style-type : none;
|
||||||
span {
|
margin-top : 0;
|
||||||
display : table-cell;
|
a {
|
||||||
&:first-child {
|
width : 100%;
|
||||||
position : relative;
|
display : flex;
|
||||||
overflow : hidden;
|
flex-flow : row nowrap;
|
||||||
&::after {
|
justify-content : space-between;
|
||||||
|
}
|
||||||
|
li + li h3 {
|
||||||
|
margin-top : 0.26cm;
|
||||||
|
line-height : 1em
|
||||||
|
}
|
||||||
|
h3 span:first-child::after {
|
||||||
|
border : none;
|
||||||
|
}
|
||||||
|
span {
|
||||||
|
display : contents;
|
||||||
|
&:first-child::after {
|
||||||
content : "";
|
content : "";
|
||||||
position : absolute;
|
|
||||||
bottom : 0.08cm;
|
bottom : 0.08cm;
|
||||||
margin-left : 0.06cm; /* Spacing before dot leaders */
|
flex : 1;
|
||||||
width : 100%;
|
margin-left : 0.08cm; /* Spacing before dot leaders */
|
||||||
|
margin-right : 0.16cm;
|
||||||
border-bottom : 0.05cm dotted #000;
|
border-bottom : 0.05cm dotted #000;
|
||||||
|
margin-bottom : 0.08cm;
|
||||||
|
}
|
||||||
|
&:last-child {
|
||||||
|
display : inline-block;
|
||||||
|
align-self : flex-end;
|
||||||
|
font-family : "BookInsanityRemake";
|
||||||
|
font-size : 0.34cm;
|
||||||
|
font-weight : normal;
|
||||||
|
color : #000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&:last-child {
|
ul { /*List indent*/
|
||||||
font-family : BookInsanityRemake;
|
margin-left : 1em;
|
||||||
font-size : 0.34cm;
|
|
||||||
font-weight : normal;
|
|
||||||
color : black;
|
|
||||||
text-align : right;
|
|
||||||
vertical-align : bottom; /* Keep page number bottom-aligned */
|
|
||||||
width : 1%;
|
|
||||||
padding-left : 0.06cm; /* Spacing after dot leaders */
|
|
||||||
/*white-space : nowrap; /* Uncomment if needed */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ul { /*List indent*/
|
&.wide{
|
||||||
margin-left : 1em;
|
.useColumns(0.96, @fillMode: balance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.wide{
|
|
||||||
.useColumns(0.96, @fillMode: balance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//*****************************
|
|
||||||
// * MUSTACHE DIVS/SPANS
|
|
||||||
// *****************************/
|
|
||||||
.page {
|
|
||||||
.block {
|
|
||||||
break-inside : avoid;
|
|
||||||
display : inline-block;
|
|
||||||
.page :where(&) {
|
|
||||||
width : 100%;
|
|
||||||
}
|
|
||||||
//-webkit-transform : translateZ(0); //Prevents shadows from breaking across columns
|
|
||||||
}
|
|
||||||
.inline-block {
|
|
||||||
display : inline-block;
|
|
||||||
text-indent : initial;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//*****************************
|
//*****************************
|
||||||
@@ -773,26 +784,13 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//*****************************
|
|
||||||
// * BLANK LINE
|
|
||||||
// *****************************/
|
|
||||||
.page {
|
|
||||||
.blank {
|
|
||||||
height : 1em;
|
|
||||||
margin-top : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//*****************************
|
//*****************************
|
||||||
// * WIDE
|
// * WIDE
|
||||||
// *****************************/
|
// *****************************/
|
||||||
.page .wide{
|
.page .wide{
|
||||||
column-span : all;
|
margin-bottom : 0.325cm;
|
||||||
-webkit-column-span : all;
|
}
|
||||||
-moz-column-span : all;
|
|
||||||
display : block;
|
.page h1 + *{
|
||||||
margin-bottom : 0.34cm;
|
margin-top : 0;
|
||||||
&+* {
|
|
||||||
margin-top : 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ body {
|
|||||||
//*****************************
|
//*****************************
|
||||||
// * BASE
|
// * BASE
|
||||||
// *****************************/
|
// *****************************/
|
||||||
:where(.page){
|
.page{
|
||||||
p{
|
p{
|
||||||
overflow-wrap : break-word;
|
overflow-wrap : break-word;
|
||||||
display : block;
|
display : block;
|
||||||
@@ -77,13 +77,7 @@ body {
|
|||||||
img{
|
img{
|
||||||
z-index : -1;
|
z-index : -1;
|
||||||
}
|
}
|
||||||
:not(:where(.wide,.columnSplit,.blank,hr)) + :where(h1,h2,h3,h4,h5,h6,table,dl,.block) {
|
|
||||||
margin-top : 1em; //NOTE: MAKE ALL MARGINS TOP-ONLY FOR BEST RESULTS WITH COLUMN BREAKS. USE * + * STYLE SELECTORS
|
|
||||||
}
|
|
||||||
|
|
||||||
:where(h1,h3,h3,h4,h5,h6) + * {
|
|
||||||
margin-top : 0;
|
|
||||||
}
|
|
||||||
//*****************************
|
//*****************************
|
||||||
// * HEADERS
|
// * HEADERS
|
||||||
// *****************************/
|
// *****************************/
|
||||||
@@ -116,6 +110,9 @@ body {
|
|||||||
font-weight : bold;
|
font-weight : bold;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
div:not(.columnWrapper) > table + table { // Side-by-side tables should not
|
||||||
|
margin-top : 0; // have vertical spacing.
|
||||||
|
}
|
||||||
|
|
||||||
/* Watermark */
|
/* Watermark */
|
||||||
.watermark {
|
.watermark {
|
||||||
@@ -191,6 +188,10 @@ body {
|
|||||||
-webkit-column-break-after : always;
|
-webkit-column-break-after : always;
|
||||||
break-after : always;
|
break-after : always;
|
||||||
-moz-column-break-after : always;
|
-moz-column-break-after : always;
|
||||||
|
margin-top : 0;
|
||||||
|
& + * {
|
||||||
|
margin-top : 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//Avoid breaking up
|
//Avoid breaking up
|
||||||
blockquote,table{
|
blockquote,table{
|
||||||
@@ -214,13 +215,11 @@ body {
|
|||||||
//*****************************
|
//*****************************
|
||||||
// * MUSTACHE DIVS/SPANS
|
// * MUSTACHE DIVS/SPANS
|
||||||
// *****************************/
|
// *****************************/
|
||||||
:where(.page) {
|
.page {
|
||||||
.block {
|
.block {
|
||||||
break-inside : avoid;
|
break-inside : avoid;
|
||||||
display : inline-block;
|
display : inline-block;
|
||||||
.page :where(&) {
|
width : 100%;
|
||||||
width : 100%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.inline-block {
|
.inline-block {
|
||||||
display : inline-block;
|
display : inline-block;
|
||||||
@@ -231,7 +230,7 @@ body {
|
|||||||
//*****************************
|
//*****************************
|
||||||
// * DEFINITION LISTS
|
// * DEFINITION LISTS
|
||||||
// *****************************/
|
// *****************************/
|
||||||
:where(.page) {
|
.page {
|
||||||
dl {
|
dl {
|
||||||
padding-left : 1em;
|
padding-left : 1em;
|
||||||
white-space : pre-line;
|
white-space : pre-line;
|
||||||
@@ -251,17 +250,20 @@ body {
|
|||||||
//*****************************
|
//*****************************
|
||||||
// * BLANK LINE
|
// * BLANK LINE
|
||||||
// *****************************/
|
// *****************************/
|
||||||
:where(.page) {
|
.page {
|
||||||
.blank {
|
.blank {
|
||||||
height : 1em;
|
height : 1em;
|
||||||
margin-top : 0;
|
margin-top : 0;
|
||||||
|
& + * {
|
||||||
|
margin-top : 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//*****************************
|
//*****************************
|
||||||
// * WIDE
|
// * WIDE
|
||||||
// *****************************/
|
// *****************************/
|
||||||
:where(.page) {
|
.page {
|
||||||
.wide{
|
.wide{
|
||||||
column-span : all;
|
column-span : all;
|
||||||
display : block;
|
display : block;
|
||||||
|
|||||||
@@ -62,7 +62,7 @@
|
|||||||
//*****************************
|
//*****************************
|
||||||
// * BASE
|
// * BASE
|
||||||
// *****************************/
|
// *****************************/
|
||||||
:where(.page){
|
.page{
|
||||||
color : var(--HB_Color_Text);
|
color : var(--HB_Color_Text);
|
||||||
font-family : ReenieBeanie;
|
font-family : ReenieBeanie;
|
||||||
font-size : 0.53cm;
|
font-size : 0.53cm;
|
||||||
@@ -554,6 +554,6 @@
|
|||||||
//*****************************
|
//*****************************
|
||||||
// * WIDE
|
// * WIDE
|
||||||
// *****************************/
|
// *****************************/
|
||||||
:where(.page) .wide {
|
.page .wide {
|
||||||
margin-bottom : 0.45cm;
|
margin-bottom : 0.45cm;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user