mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-09-24 13:52:58 +00:00
Merge branch 'master' into fix-deletion-of-orphan-stubs
This commit is contained in:
@@ -23,7 +23,6 @@ import safeHTML from './safeHTML.js';
|
|||||||
const PAGEBREAK_REGEX_V3 = /^(?=\\page(?:break)?(?: *{[^\n{}]*})?$)/m;
|
const PAGEBREAK_REGEX_V3 = /^(?=\\page(?:break)?(?: *{[^\n{}]*})?$)/m;
|
||||||
const PAGEBREAK_REGEX_LEGACY = /\\page(?:break)?/m;
|
const PAGEBREAK_REGEX_LEGACY = /\\page(?:break)?/m;
|
||||||
const COLUMNBREAK_REGEX_LEGACY = /\\column(:?break)?/m;
|
const COLUMNBREAK_REGEX_LEGACY = /\\column(:?break)?/m;
|
||||||
const PAGE_HEIGHT = 1056;
|
|
||||||
|
|
||||||
const TOOLBAR_STATE_KEY = 'HB_renderer_toolbarState';
|
const TOOLBAR_STATE_KEY = 'HB_renderer_toolbarState';
|
||||||
|
|
||||||
@@ -47,31 +46,25 @@ const BrewPage = (props)=>{
|
|||||||
};
|
};
|
||||||
const pageRef = useRef(null);
|
const pageRef = useRef(null);
|
||||||
const cleanText = safeHTML(props.contents);
|
const cleanText = safeHTML(props.contents);
|
||||||
|
const pageNum = props.index + 1;
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
if(!pageRef.current) return;
|
if(!pageRef.current) return;
|
||||||
|
|
||||||
// Observer for tracking pages within the `.pages` div
|
// Observer for tracking which pages are at least 30% visible in the iframe
|
||||||
const visibleObserver = new IntersectionObserver(
|
const visibleObserver = new IntersectionObserver(
|
||||||
(entries)=>{
|
(entries)=>entries.forEach((entry)=>{
|
||||||
entries.forEach((entry)=>{
|
props.onVisibilityChange(pageNum, entry.isIntersecting, false); // add page to array of visible pages.
|
||||||
if(entry.isIntersecting)
|
}),
|
||||||
props.onVisibilityChange(props.index + 1, true, false); // add page to array of visible pages.
|
|
||||||
else
|
|
||||||
props.onVisibilityChange(props.index + 1, false, false);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
{ threshold: .3, rootMargin: '0px 0px 0px 0px' } // detect when >30% of page is within bounds.
|
{ threshold: .3, rootMargin: '0px 0px 0px 0px' } // detect when >30% of page is within bounds.
|
||||||
);
|
);
|
||||||
|
|
||||||
// Observer for tracking the page at the center of the iframe.
|
// Observer for tracking the page at the center of the iframe.
|
||||||
const centerObserver = new IntersectionObserver(
|
const centerObserver = new IntersectionObserver(
|
||||||
(entries)=>{
|
(entries)=>entries.forEach((entry)=>{
|
||||||
entries.forEach((entry)=>{
|
if(entry.isIntersecting)
|
||||||
if(entry.isIntersecting)
|
props.onVisibilityChange(pageNum, true, true); // Set this page as the center page
|
||||||
props.onVisibilityChange(props.index + 1, true, true); // Set this page as the center page
|
}),
|
||||||
});
|
|
||||||
},
|
|
||||||
{ threshold: 0, rootMargin: '-50% 0px -50% 0px' } // Detect when the page is at the center
|
{ threshold: 0, rootMargin: '-50% 0px -50% 0px' } // Detect when the page is at the center
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -92,7 +85,7 @@ const BrewPage = (props)=>{
|
|||||||
|
|
||||||
//v=====--------------------< Brew Renderer Component >-------------------=====v//
|
//v=====--------------------< Brew Renderer Component >-------------------=====v//
|
||||||
let renderedPages = [];
|
let renderedPages = [];
|
||||||
let pageTemplates = [];
|
const pageTemplates = [];
|
||||||
let rawPages = [];
|
let rawPages = [];
|
||||||
|
|
||||||
const BrewRenderer = (props)=>{
|
const BrewRenderer = (props)=>{
|
||||||
@@ -100,22 +93,21 @@ const BrewRenderer = (props)=>{
|
|||||||
text : '',
|
text : '',
|
||||||
style : '',
|
style : '',
|
||||||
renderer : 'legacy',
|
renderer : 'legacy',
|
||||||
theme : '5ePHB',
|
|
||||||
lang : '',
|
lang : '',
|
||||||
errors : [],
|
errors : [],
|
||||||
currentEditorCursorPageNum : 1,
|
currentEditorCursorPageNum : 1,
|
||||||
currentEditorViewPageNum : 1,
|
|
||||||
currentBrewRendererPageNum : 1,
|
currentBrewRendererPageNum : 1,
|
||||||
themeBundle : {},
|
themeBundle : {},
|
||||||
onPageChange : ()=>{},
|
onPageChange : ()=>{},
|
||||||
...props
|
...props
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const [visiblePages, setVisiblePages] = useState([]);
|
||||||
|
const [centerPage , setCenterPage ] = useState(1);
|
||||||
|
|
||||||
const [state, setState] = useState({
|
const [state, setState] = useState({
|
||||||
isMounted : false,
|
isMounted : false,
|
||||||
visibility : 'hidden',
|
visibility : 'hidden'
|
||||||
visiblePages : [],
|
|
||||||
centerPage : 1
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const [displayOptions, setDisplayOptions] = useState({
|
const [displayOptions, setDisplayOptions] = useState({
|
||||||
@@ -135,9 +127,7 @@ const BrewRenderer = (props)=>{
|
|||||||
|
|
||||||
const [headerState, setHeaderState] = useState(false);
|
const [headerState, setHeaderState] = useState(false);
|
||||||
|
|
||||||
const mainRef = useRef(null);
|
|
||||||
const pagesRef = useRef(null);
|
const pagesRef = useRef(null);
|
||||||
const urlRef = useRef('');
|
|
||||||
|
|
||||||
if(props.renderer == 'legacy') {
|
if(props.renderer == 'legacy') {
|
||||||
rawPages = props.text.split(PAGEBREAK_REGEX_LEGACY);
|
rawPages = props.text.split(PAGEBREAK_REGEX_LEGACY);
|
||||||
@@ -146,20 +136,16 @@ const BrewRenderer = (props)=>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handlePageVisibilityChange = (pageNum, isVisible, isCenter)=>{
|
const handlePageVisibilityChange = (pageNum, isVisible, isCenter)=>{
|
||||||
setState((prevState)=>{
|
setVisiblePages((prev)=>{
|
||||||
const updatedVisiblePages = new Set(prevState.visiblePages);
|
const updatedVisiblePages = new Set(prev);
|
||||||
if(!isCenter)
|
isVisible ? updatedVisiblePages.add(pageNum) : updatedVisiblePages.delete(pageNum);
|
||||||
isVisible ? updatedVisiblePages.add(pageNum) : updatedVisiblePages.delete(pageNum);
|
return [...updatedVisiblePages].sort((a, b)=>a - b);
|
||||||
|
|
||||||
return {
|
|
||||||
...prevState,
|
|
||||||
visiblePages : [...updatedVisiblePages].sort((a, b)=>a - b),
|
|
||||||
centerPage : isCenter ? pageNum : prevState.centerPage
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if(isCenter)
|
if(isCenter) {
|
||||||
|
setCenterPage(pageNum);
|
||||||
props.onPageChange(pageNum);
|
props.onPageChange(pageNum);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const isInView = (index)=>{
|
const isInView = (index)=>{
|
||||||
@@ -341,19 +327,19 @@ const BrewRenderer = (props)=>{
|
|||||||
: null}
|
: null}
|
||||||
|
|
||||||
<ErrorBar errors={props.errors} />
|
<ErrorBar errors={props.errors} />
|
||||||
<div className='popups' ref={mainRef}>
|
<div className='popups'>
|
||||||
<RenderWarnings />
|
<RenderWarnings />
|
||||||
<NotificationPopup />
|
<NotificationPopup />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ToolBar displayOptions={displayOptions} onDisplayOptionsChange={handleDisplayOptionsChange} visiblePages={state.visiblePages.length > 0 ? state.visiblePages : [state.centerPage]} totalPages={rawPages.length} headerState={headerState} setHeaderState={setHeaderState}/>
|
<ToolBar displayOptions={displayOptions} onDisplayOptionsChange={handleDisplayOptionsChange} visiblePages={visiblePages.length > 0 ? visiblePages : [centerPage]} totalPages={rawPages.length} headerState={headerState} setHeaderState={setHeaderState}/>
|
||||||
|
|
||||||
{/*render in iFrame so broken code doesn't crash the site.*/}
|
{/*render in iFrame so broken code doesn't crash the site.*/}
|
||||||
<Frame id='BrewRenderer' title="Rendered Brew Content" initialContent={INITIAL_CONTENT}
|
<Frame id='BrewRenderer' title='Rendered Brew Content' initialContent={INITIAL_CONTENT}
|
||||||
style={{ width: '100%', height: '100%', visibility: state.visibility }}
|
style={{ width: '100%', height: '100%', visibility: state.visibility }}
|
||||||
contentDidMount={frameDidMount}
|
contentDidMount={frameDidMount}
|
||||||
onClick={()=>{emitClick();}}
|
onClick={()=>{emitClick();}}
|
||||||
sandbox="allow-same-origin allow-modals allow-top-navigation"
|
sandbox='allow-same-origin allow-modals allow-top-navigation'
|
||||||
>
|
>
|
||||||
<div className='brewRenderer'
|
<div className='brewRenderer'
|
||||||
onKeyDown={handleControlKeys}
|
onKeyDown={handleControlKeys}
|
||||||
|
|||||||
@@ -1,34 +1,28 @@
|
|||||||
import './navbar.less';
|
import './navbar.less';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import createReactClass from 'create-react-class';
|
|
||||||
|
|
||||||
import Nav from './nav.jsx';
|
import Nav from './nav.jsx';
|
||||||
import PatreonNavItem from './patreon.navitem.jsx';
|
import PatreonNavItem from './patreon.navitem.jsx';
|
||||||
|
|
||||||
const Navbar = createReactClass({
|
const Navbar = ({ children })=>{
|
||||||
displayName : 'Navbar',
|
const version = global.version || '0.0.0';
|
||||||
getInitialState : function() {
|
|
||||||
return {
|
|
||||||
ver : global.version || '0.0.0'
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
render : function(){
|
return (
|
||||||
return <Nav.base>
|
<Nav.base>
|
||||||
<Nav.section>
|
<Nav.section>
|
||||||
<Nav.logo />
|
<Nav.logo />
|
||||||
<Nav.item href='/' className='homebrewLogo'>
|
<Nav.item href='/' className='homebrewLogo'>
|
||||||
<div>The Homebrewery</div>
|
<div>The Homebrewery</div>
|
||||||
</Nav.item>
|
</Nav.item>
|
||||||
<Nav.item newTab={true} href='/changelog' color='purple' icon='far fa-file-alt'>
|
<Nav.item newTab={true} href='/changelog' color='purple' icon='far fa-file-alt'>
|
||||||
{`v${this.state.ver}`}
|
{`v${version}`}
|
||||||
</Nav.item>
|
</Nav.item>
|
||||||
<PatreonNavItem />
|
<PatreonNavItem />
|
||||||
{/*this.renderChromeWarning()*/}
|
{/* this.renderChromeWarning() */}
|
||||||
</Nav.section>
|
</Nav.section>
|
||||||
{this.props.children}
|
{children}
|
||||||
</Nav.base>;
|
</Nav.base>
|
||||||
}
|
);
|
||||||
});
|
};
|
||||||
|
|
||||||
export default Navbar;
|
export default Navbar;
|
||||||
@@ -9,7 +9,7 @@ import _ from 'lodash';
|
|||||||
|
|
||||||
import { DEFAULT_BREW_LOAD } from '../../../../server/brewDefaults.js';
|
import { DEFAULT_BREW_LOAD } from '../../../../server/brewDefaults.js';
|
||||||
|
|
||||||
import useCommonEditPageFunctions from '../../utils/commonEditPageFunctions.js'
|
import useCommonEditPageFunctions from '../../utils/commonEditPageFunctions.jsx'
|
||||||
|
|
||||||
import SplitPane from '@components/splitPane/splitPane.jsx';
|
import SplitPane from '@components/splitPane/splitPane.jsx';
|
||||||
import Editor from '../../editor/editor.jsx';
|
import Editor from '../../editor/editor.jsx';
|
||||||
@@ -53,8 +53,6 @@ const EditPage = (props)=>{
|
|||||||
};
|
};
|
||||||
|
|
||||||
const [currentBrew, setCurrentBrew] = useState(props.brew);
|
const [currentBrew, setCurrentBrew] = useState(props.brew);
|
||||||
const [isSaving, setIsSaving] = useState(false);
|
|
||||||
const [lastSavedTime, setLastSavedTime] = useState(new Date());
|
|
||||||
const [saveGoogle, setSaveGoogle] = useState(!!props.brew.googleId);
|
const [saveGoogle, setSaveGoogle] = useState(!!props.brew.googleId);
|
||||||
const [error, setError] = useState(null);
|
const [error, setError] = useState(null);
|
||||||
const [HTMLErrors, setHTMLErrors] = useState(hbfm.validate(props.brew.text));
|
const [HTMLErrors, setHTMLErrors] = useState(hbfm.validate(props.brew.text));
|
||||||
@@ -62,13 +60,10 @@ const EditPage = (props)=>{
|
|||||||
const [currentEditorCursorPageNum, setCurrentEditorCursorPageNum] = useState(1);
|
const [currentEditorCursorPageNum, setCurrentEditorCursorPageNum] = useState(1);
|
||||||
const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1);
|
const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1);
|
||||||
const [themeBundle, setThemeBundle] = useState({});
|
const [themeBundle, setThemeBundle] = useState({});
|
||||||
const [unsavedChanges, setUnsavedChanges] = useState(false);
|
|
||||||
const [alertTrashedGoogleBrew, setAlertTrashedGoogleBrew] = useState(props.brew.trashed);
|
const [alertTrashedGoogleBrew, setAlertTrashedGoogleBrew] = useState(props.brew.trashed);
|
||||||
const [alertNoGoogleToTransfer, setAlertNoGoogleToTransfer] = useState(false);
|
const [alertNoGoogleToTransfer, setAlertNoGoogleToTransfer] = useState(false);
|
||||||
const [alertOwnershipToTransfer, setAlertOwnershipToTransfer] = useState(false);
|
const [alertOwnershipToTransfer, setAlertOwnershipToTransfer] = useState(false);
|
||||||
const [confirmGoogleTransfer, setConfirmGoogleTransfer] = useState(false);
|
const [confirmGoogleTransfer, setConfirmGoogleTransfer] = useState(false);
|
||||||
const [autoSaveEnabled, setAutoSaveEnabled] = useState(true);
|
|
||||||
const [warnUnsavedChanges, setWarnUnsavedChanges] = useState(true);
|
|
||||||
|
|
||||||
const editorRef = useRef(null);
|
const editorRef = useRef(null);
|
||||||
const lastSavedBrew = useRef(_.cloneDeep(props.brew));
|
const lastSavedBrew = useRef(_.cloneDeep(props.brew));
|
||||||
@@ -206,52 +201,12 @@ const EditPage = (props)=>{
|
|||||||
</Nav.item>
|
</Nav.item>
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderSaveButton = ()=>{
|
|
||||||
// #1 - Currently saving, show SAVING
|
|
||||||
if(isSaving)
|
|
||||||
return <Nav.item className='save' icon='fas fa-spinner fa-spin'>saving...</Nav.item>;
|
|
||||||
|
|
||||||
// #2 - Unsaved changes exist, autosave is OFF and warning timer has expired, show AUTOSAVE WARNING
|
|
||||||
if(unsavedChanges && warnUnsavedChanges) {
|
|
||||||
resetWarnUnsavedTimer();
|
|
||||||
const elapsedTime = Math.round((new Date() - lastSavedTime) / 1000 / 60);
|
|
||||||
const text = elapsedTime === 0
|
|
||||||
? `Autosave is OFF${sandbox ? ' for this sandbox page' : ''}.`
|
|
||||||
: `Autosave is OFF${sandbox ? ' for this sandbox page' : ''}, 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>;
|
|
||||||
}
|
|
||||||
|
|
||||||
// #3 - Unsaved changes exist, click to save, show SAVE NOW
|
|
||||||
if(unsavedChanges)
|
|
||||||
return <Nav.item className='save' onClick={()=>trySave(true, true, saveGoogle)} color='blue' icon='fas fa-save'>save now</Nav.item>;
|
|
||||||
|
|
||||||
// #4 - No unsaved changes, autosave is ON, show AUTO-SAVED
|
|
||||||
if(autoSaveEnabled)
|
|
||||||
return <Nav.item className='save saved'>auto-saved</Nav.item>;
|
|
||||||
|
|
||||||
// #5 - Sandbox with no unsaved changes, and has never been saved, hide the button
|
|
||||||
if(sandbox)
|
|
||||||
return <Nav.item className='save sandbox' disabled={true}>save now</Nav.item>;
|
|
||||||
|
|
||||||
// DEFAULT - No unsaved changes, show SAVED
|
|
||||||
return <Nav.item className='save saved'>saved</Nav.item>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderAutoSaveButton = ()=>(
|
const renderAutoSaveButton = ()=>(
|
||||||
<Nav.item onClick={toggleAutoSave}>
|
<Nav.item onClick={toggleAutoSave}>
|
||||||
Autosave <i className={autoSaveEnabled ? 'fas fa-power-off active' : 'fas fa-power-off'}></i>
|
Autosave <i className={autoSaveEnabled ? 'fas fa-power-off active' : 'fas fa-power-off'}></i>
|
||||||
</Nav.item>
|
</Nav.item>
|
||||||
);
|
);
|
||||||
|
|
||||||
const clearError = ()=>{
|
|
||||||
setError(null);
|
|
||||||
setIsSaving(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderNavbar = ()=>{
|
const renderNavbar = ()=>{
|
||||||
return <Navbar>
|
return <Navbar>
|
||||||
<Nav.section>
|
<Nav.section>
|
||||||
@@ -278,10 +233,12 @@ const EditPage = (props)=>{
|
|||||||
};
|
};
|
||||||
|
|
||||||
const {
|
const {
|
||||||
resetWarnUnsavedTimer,
|
|
||||||
handleSplitMove,
|
handleSplitMove,
|
||||||
handleBrewChange,
|
handleBrewChange,
|
||||||
toggleAutoSave,
|
toggleAutoSave,
|
||||||
|
clearError,
|
||||||
|
renderSaveButton,
|
||||||
|
autoSaveEnabled,
|
||||||
trySave
|
trySave
|
||||||
} = useCommonEditPageFunctions({
|
} = useCommonEditPageFunctions({
|
||||||
saveGoogle,
|
saveGoogle,
|
||||||
@@ -297,19 +254,10 @@ const EditPage = (props)=>{
|
|||||||
SNIPKEY,
|
SNIPKEY,
|
||||||
METAKEY,
|
METAKEY,
|
||||||
hbfm,
|
hbfm,
|
||||||
autoSaveEnabled,
|
|
||||||
setAutoSaveEnabled,
|
|
||||||
setWarnUnsavedChanges,
|
|
||||||
unsavedChanges,
|
|
||||||
setUnsavedChanges,
|
|
||||||
sandbox,
|
sandbox,
|
||||||
lastSavedBrew,
|
lastSavedBrew,
|
||||||
editorRef,
|
editorRef,
|
||||||
isSaving,
|
|
||||||
setIsSaving,
|
|
||||||
save,
|
save,
|
||||||
lastSavedTime,
|
|
||||||
setLastSavedTime
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -341,12 +289,10 @@ const EditPage = (props)=>{
|
|||||||
text={currentBrew.text}
|
text={currentBrew.text}
|
||||||
style={currentBrew.style}
|
style={currentBrew.style}
|
||||||
renderer={currentBrew.renderer}
|
renderer={currentBrew.renderer}
|
||||||
theme={currentBrew.theme}
|
|
||||||
themeBundle={themeBundle}
|
themeBundle={themeBundle}
|
||||||
errors={HTMLErrors}
|
errors={HTMLErrors}
|
||||||
lang={currentBrew.lang}
|
lang={currentBrew.lang}
|
||||||
onPageChange={setCurrentBrewRendererPageNum}
|
onPageChange={setCurrentBrewRendererPageNum}
|
||||||
currentEditorViewPageNum={currentEditorViewPageNum}
|
|
||||||
currentEditorCursorPageNum={currentEditorCursorPageNum}
|
currentEditorCursorPageNum={currentEditorCursorPageNum}
|
||||||
currentBrewRendererPageNum={currentBrewRendererPageNum}
|
currentBrewRendererPageNum={currentBrewRendererPageNum}
|
||||||
allowPrint={true}
|
allowPrint={true}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import _ from 'lodash';
|
|||||||
|
|
||||||
import { DEFAULT_BREW } from '../../../../server/brewDefaults.js';
|
import { DEFAULT_BREW } from '../../../../server/brewDefaults.js';
|
||||||
|
|
||||||
import useCommonEditPageFunctions from '../../utils/commonEditPageFunctions.js'
|
import useCommonEditPageFunctions from '../../utils/commonEditPageFunctions.jsx'
|
||||||
|
|
||||||
import SplitPane from '@components/splitPane/splitPane.jsx';
|
import SplitPane from '@components/splitPane/splitPane.jsx';
|
||||||
import Editor from '../../editor/editor.jsx';
|
import Editor from '../../editor/editor.jsx';
|
||||||
@@ -53,11 +53,6 @@ const HomePage =(props)=>{
|
|||||||
const [currentEditorCursorPageNum, setCurrentEditorCursorPageNum] = useState(1);
|
const [currentEditorCursorPageNum, setCurrentEditorCursorPageNum] = useState(1);
|
||||||
const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1);
|
const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1);
|
||||||
const [themeBundle, setThemeBundle] = useState({});
|
const [themeBundle, setThemeBundle] = useState({});
|
||||||
const [unsavedChanges, setUnsavedChanges] = useState(false);
|
|
||||||
const [isSaving, setIsSaving] = useState(false);
|
|
||||||
const [lastSavedTime, setLastSavedTime] = useState(new Date());
|
|
||||||
const [autoSaveEnabled, setAutoSaveEnabled] = useState(false);
|
|
||||||
const [warnUnsavedChanges, setWarnUnsavedChanges] = useState(true);
|
|
||||||
|
|
||||||
const editorRef = useRef(null);
|
const editorRef = useRef(null);
|
||||||
const lastSavedBrew = useRef(_.cloneDeep(props.brew));
|
const lastSavedBrew = useRef(_.cloneDeep(props.brew));
|
||||||
@@ -77,46 +72,6 @@ const HomePage =(props)=>{
|
|||||||
window.location = `/edit/${saved.editId}`;
|
window.location = `/edit/${saved.editId}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderSaveButton = ()=>{
|
|
||||||
// #1 - Currently saving, show SAVING
|
|
||||||
if(isSaving)
|
|
||||||
return <Nav.item className='save' icon='fas fa-spinner fa-spin'>saving...</Nav.item>;
|
|
||||||
|
|
||||||
// #2 - Unsaved changes exist, autosave is OFF and warning timer has expired, show AUTOSAVE WARNING
|
|
||||||
if(unsavedChanges && warnUnsavedChanges) {
|
|
||||||
resetWarnUnsavedTimer();
|
|
||||||
const elapsedTime = Math.round((new Date() - lastSavedTime) / 1000 / 60);
|
|
||||||
const text = elapsedTime === 0
|
|
||||||
? `Autosave is OFF${sandbox ? ' for this sandbox page' : ''}.`
|
|
||||||
: `Autosave is OFF${sandbox ? ' for this sandbox page' : ''}, 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>;
|
|
||||||
}
|
|
||||||
|
|
||||||
// #3 - Unsaved changes exist, click to save, show SAVE NOW
|
|
||||||
if(unsavedChanges)
|
|
||||||
return <Nav.item className='save' onClick={()=>trySave(true, true, saveGoogle)} color='blue' icon='fas fa-save'>save now</Nav.item>;
|
|
||||||
|
|
||||||
// #4 - No unsaved changes, autosave is ON, show AUTO-SAVED
|
|
||||||
if(autoSaveEnabled)
|
|
||||||
return <Nav.item className='save saved'>auto-saved</Nav.item>;
|
|
||||||
|
|
||||||
// #5 - Sandbox with no unsaved changes, and has never been saved, hide the button
|
|
||||||
if(sandbox)
|
|
||||||
return <Nav.item className='save neverSaved' disabled={true}>save now</Nav.item>;
|
|
||||||
|
|
||||||
// DEFAULT - No unsaved changes, show SAVED
|
|
||||||
return <Nav.item className='save saved'>saved</Nav.item>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const clearError = ()=>{
|
|
||||||
setError(null);
|
|
||||||
setIsSaving(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderNavbar = ()=>{
|
const renderNavbar = ()=>{
|
||||||
return <Navbar ver={props.ver}>
|
return <Navbar ver={props.ver}>
|
||||||
<Nav.section>
|
<Nav.section>
|
||||||
@@ -134,9 +89,11 @@ const HomePage =(props)=>{
|
|||||||
};
|
};
|
||||||
|
|
||||||
const {
|
const {
|
||||||
resetWarnUnsavedTimer,
|
|
||||||
handleSplitMove,
|
handleSplitMove,
|
||||||
handleBrewChange,
|
handleBrewChange,
|
||||||
|
clearError,
|
||||||
|
renderSaveButton,
|
||||||
|
unsavedChanges,
|
||||||
trySave
|
trySave
|
||||||
} = useCommonEditPageFunctions({
|
} = useCommonEditPageFunctions({
|
||||||
saveGoogle,
|
saveGoogle,
|
||||||
@@ -152,19 +109,10 @@ const HomePage =(props)=>{
|
|||||||
SNIPKEY,
|
SNIPKEY,
|
||||||
METAKEY,
|
METAKEY,
|
||||||
hbfm,
|
hbfm,
|
||||||
autoSaveEnabled,
|
|
||||||
setAutoSaveEnabled,
|
|
||||||
setWarnUnsavedChanges,
|
|
||||||
unsavedChanges,
|
|
||||||
setUnsavedChanges,
|
|
||||||
sandbox,
|
sandbox,
|
||||||
lastSavedBrew,
|
lastSavedBrew,
|
||||||
editorRef,
|
editorRef,
|
||||||
isSaving,
|
|
||||||
setIsSaving,
|
|
||||||
save,
|
save,
|
||||||
lastSavedTime,
|
|
||||||
setLastSavedTime
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -190,11 +138,10 @@ const HomePage =(props)=>{
|
|||||||
text={currentBrew.text}
|
text={currentBrew.text}
|
||||||
style={currentBrew.style}
|
style={currentBrew.style}
|
||||||
renderer={currentBrew.renderer}
|
renderer={currentBrew.renderer}
|
||||||
|
themeBundle={themeBundle}
|
||||||
onPageChange={setCurrentBrewRendererPageNum}
|
onPageChange={setCurrentBrewRendererPageNum}
|
||||||
currentEditorViewPageNum={currentEditorViewPageNum}
|
|
||||||
currentEditorCursorPageNum={currentEditorCursorPageNum}
|
currentEditorCursorPageNum={currentEditorCursorPageNum}
|
||||||
currentBrewRendererPageNum={currentBrewRendererPageNum}
|
currentBrewRendererPageNum={currentBrewRendererPageNum}
|
||||||
themeBundle={themeBundle}
|
|
||||||
/>
|
/>
|
||||||
</SplitPane>
|
</SplitPane>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import _ from 'lodash';
|
|||||||
import { DEFAULT_BREW } from '../../../../server/brewDefaults.js';
|
import { DEFAULT_BREW } from '../../../../server/brewDefaults.js';
|
||||||
import { printCurrentBrew, fetchThemeBundle, splitTextStyleAndMetadata } from '@shared/helpers.js';
|
import { printCurrentBrew, fetchThemeBundle, splitTextStyleAndMetadata } from '@shared/helpers.js';
|
||||||
|
|
||||||
import useCommonEditPageFunctions from '../../utils/commonEditPageFunctions.js'
|
import useCommonEditPageFunctions from '../../utils/commonEditPageFunctions.jsx'
|
||||||
|
|
||||||
import SplitPane from '@components/splitPane/splitPane.jsx';
|
import SplitPane from '@components/splitPane/splitPane.jsx';
|
||||||
import Editor from '../../editor/editor.jsx';
|
import Editor from '../../editor/editor.jsx';
|
||||||
@@ -45,8 +45,6 @@ const NewPage = (props)=>{
|
|||||||
};
|
};
|
||||||
|
|
||||||
const [currentBrew, setCurrentBrew] = useState(props.brew);
|
const [currentBrew, setCurrentBrew] = useState(props.brew);
|
||||||
const [isSaving, setIsSaving] = useState(false);
|
|
||||||
const [lastSavedTime, setLastSavedTime] = useState(new Date());
|
|
||||||
const [saveGoogle, setSaveGoogle] = useState(global.account?.googleId ? true : false);
|
const [saveGoogle, setSaveGoogle] = useState(global.account?.googleId ? true : false);
|
||||||
const [error, setError] = useState(null);
|
const [error, setError] = useState(null);
|
||||||
const [HTMLErrors, setHTMLErrors] = useState(hbfm.validate(props.brew.text));
|
const [HTMLErrors, setHTMLErrors] = useState(hbfm.validate(props.brew.text));
|
||||||
@@ -54,9 +52,6 @@ const NewPage = (props)=>{
|
|||||||
const [currentEditorCursorPageNum, setCurrentEditorCursorPageNum] = useState(1);
|
const [currentEditorCursorPageNum, setCurrentEditorCursorPageNum] = useState(1);
|
||||||
const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1);
|
const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1);
|
||||||
const [themeBundle, setThemeBundle] = useState({});
|
const [themeBundle, setThemeBundle] = useState({});
|
||||||
const [unsavedChanges, setUnsavedChanges] = useState(false);
|
|
||||||
const [autoSaveEnabled, setAutoSaveEnabled] = useState(false);
|
|
||||||
const [warnUnsavedChanges, setWarnUnsavedChanges] = useState(true);
|
|
||||||
|
|
||||||
const editorRef = useRef(null);
|
const editorRef = useRef(null);
|
||||||
const lastSavedBrew = useRef(_.cloneDeep(props.brew));
|
const lastSavedBrew = useRef(_.cloneDeep(props.brew));
|
||||||
@@ -121,46 +116,6 @@ const NewPage = (props)=>{
|
|||||||
window.location = `/edit/${savedBrew.editId}`;
|
window.location = `/edit/${savedBrew.editId}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderSaveButton = ()=>{
|
|
||||||
// #1 - Currently saving, show SAVING
|
|
||||||
if(isSaving)
|
|
||||||
return <Nav.item className='save' icon='fas fa-spinner fa-spin'>saving...</Nav.item>;
|
|
||||||
|
|
||||||
// #2 - Unsaved changes exist, autosave is OFF and warning timer has expired, show AUTOSAVE WARNING
|
|
||||||
if(unsavedChanges && warnUnsavedChanges) {
|
|
||||||
resetWarnUnsavedTimer();
|
|
||||||
const elapsedTime = Math.round((new Date() - lastSavedTime) / 1000 / 60);
|
|
||||||
const text = elapsedTime === 0
|
|
||||||
? `Autosave is OFF${sandbox ? ' for this sandbox page' : ''}.`
|
|
||||||
: `Autosave is OFF${sandbox ? ' for this sandbox page' : ''}, 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>;
|
|
||||||
}
|
|
||||||
|
|
||||||
// #3 - Unsaved changes exist, click to save, show SAVE NOW
|
|
||||||
if(unsavedChanges)
|
|
||||||
return <Nav.item className='save' onClick={()=>trySave(true, true, saveGoogle)} color='blue' icon='fas fa-save'>save now</Nav.item>;
|
|
||||||
|
|
||||||
// #4 - No unsaved changes, autosave is ON, show AUTO-SAVED
|
|
||||||
if(autoSaveEnabled)
|
|
||||||
return <Nav.item className='save saved'>auto-saved</Nav.item>;
|
|
||||||
|
|
||||||
// #5 - Sandbox with no unsaved changes, and has never been saved, hide the button
|
|
||||||
if(sandbox)
|
|
||||||
return <Nav.item className='save neverSaved' disabled={true}>save now</Nav.item>;
|
|
||||||
|
|
||||||
// DEFAULT - No unsaved changes, show SAVED
|
|
||||||
return <Nav.item className='save saved'>saved</Nav.item>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const clearError = ()=>{
|
|
||||||
setError(null);
|
|
||||||
setIsSaving(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderNavbar = ()=>(
|
const renderNavbar = ()=>(
|
||||||
<Navbar>
|
<Navbar>
|
||||||
<Nav.section>
|
<Nav.section>
|
||||||
@@ -182,10 +137,10 @@ const NewPage = (props)=>{
|
|||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
resetWarnUnsavedTimer,
|
|
||||||
handleSplitMove,
|
handleSplitMove,
|
||||||
handleBrewChange,
|
handleBrewChange,
|
||||||
trySave
|
clearError,
|
||||||
|
renderSaveButton
|
||||||
} = useCommonEditPageFunctions({
|
} = useCommonEditPageFunctions({
|
||||||
saveGoogle,
|
saveGoogle,
|
||||||
setError,
|
setError,
|
||||||
@@ -200,19 +155,10 @@ const NewPage = (props)=>{
|
|||||||
SNIPKEY,
|
SNIPKEY,
|
||||||
METAKEY,
|
METAKEY,
|
||||||
hbfm,
|
hbfm,
|
||||||
autoSaveEnabled,
|
|
||||||
setAutoSaveEnabled,
|
|
||||||
setWarnUnsavedChanges,
|
|
||||||
unsavedChanges,
|
|
||||||
setUnsavedChanges,
|
|
||||||
sandbox,
|
sandbox,
|
||||||
lastSavedBrew,
|
lastSavedBrew,
|
||||||
editorRef,
|
editorRef,
|
||||||
isSaving,
|
|
||||||
setIsSaving,
|
|
||||||
save,
|
save,
|
||||||
lastSavedTime,
|
|
||||||
setLastSavedTime
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -237,12 +183,10 @@ const NewPage = (props)=>{
|
|||||||
text={currentBrew.text}
|
text={currentBrew.text}
|
||||||
style={currentBrew.style}
|
style={currentBrew.style}
|
||||||
renderer={currentBrew.renderer}
|
renderer={currentBrew.renderer}
|
||||||
theme={currentBrew.theme}
|
|
||||||
themeBundle={themeBundle}
|
themeBundle={themeBundle}
|
||||||
errors={HTMLErrors}
|
errors={HTMLErrors}
|
||||||
lang={currentBrew.lang}
|
lang={currentBrew.lang}
|
||||||
onPageChange={setCurrentBrewRendererPageNum}
|
onPageChange={setCurrentBrewRendererPageNum}
|
||||||
currentEditorViewPageNum={currentEditorViewPageNum}
|
|
||||||
currentEditorCursorPageNum={currentEditorCursorPageNum}
|
currentEditorCursorPageNum={currentEditorCursorPageNum}
|
||||||
currentBrewRendererPageNum={currentBrewRendererPageNum}
|
currentBrewRendererPageNum={currentBrewRendererPageNum}
|
||||||
allowPrint={true}
|
allowPrint={true}
|
||||||
|
|||||||
+45
-11
@@ -1,6 +1,7 @@
|
|||||||
import React, { useState, useEffect, useEffectEvent, useRef } from 'react';
|
import React, { useState, useEffect, useEffectEvent, useRef } from 'react';
|
||||||
import { printCurrentBrew, fetchThemeBundle } from '@shared/helpers.js';
|
import { printCurrentBrew, fetchThemeBundle } from '@shared/helpers.js';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import Nav from '@navbar/nav.jsx';
|
||||||
|
|
||||||
const AUTOSAVE_KEY = 'HB_editor_autoSaveOn';
|
const AUTOSAVE_KEY = 'HB_editor_autoSaveOn';
|
||||||
|
|
||||||
@@ -23,21 +24,18 @@ export default function useCommonEditPageFunctions(dependencies) {
|
|||||||
SNIPKEY,
|
SNIPKEY,
|
||||||
METAKEY,
|
METAKEY,
|
||||||
hbfm,
|
hbfm,
|
||||||
autoSaveEnabled,
|
|
||||||
setAutoSaveEnabled,
|
|
||||||
setWarnUnsavedChanges,
|
|
||||||
sandbox,
|
sandbox,
|
||||||
unsavedChanges,
|
|
||||||
setUnsavedChanges,
|
|
||||||
lastSavedBrew,
|
lastSavedBrew,
|
||||||
editorRef,
|
editorRef,
|
||||||
isSaving,
|
|
||||||
setIsSaving,
|
|
||||||
save,
|
save,
|
||||||
lastSavedTime,
|
|
||||||
setLastSavedTime
|
|
||||||
} = dependencies;
|
} = dependencies;
|
||||||
|
|
||||||
|
const [isSaving , setIsSaving] = useState(false);
|
||||||
|
const [lastSavedTime , setLastSavedTime] = useState(new Date());
|
||||||
|
const [autoSaveEnabled , setAutoSaveEnabled] = useState(!sandbox);
|
||||||
|
const [warnUnsavedChanges, setWarnUnsavedChanges] = useState(true);
|
||||||
|
const [unsavedChanges , setUnsavedChanges] = useState(false);
|
||||||
|
|
||||||
const unsavedChangesRef = useRef(unsavedChanges); // onBeforeUnload lives outside React and needs ref to unsavedChanges
|
const unsavedChangesRef = useRef(unsavedChanges); // onBeforeUnload lives outside React and needs ref to unsavedChanges
|
||||||
const warnUnsavedTimeout = useRef(null); // timers live outside React and need ref to consistently track time
|
const warnUnsavedTimeout = useRef(null); // timers live outside React and need ref to consistently track time
|
||||||
const saveTimeout = useRef(null);
|
const saveTimeout = useRef(null);
|
||||||
@@ -59,7 +57,6 @@ export default function useCommonEditPageFunctions(dependencies) {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener('keydown', handleControlKeys);
|
document.addEventListener('keydown', handleControlKeys);
|
||||||
window.onbeforeunload = ()=>{
|
window.onbeforeunload = ()=>{
|
||||||
if(unsavedChangesRef.current)
|
if(unsavedChangesRef.current)
|
||||||
@@ -121,6 +118,11 @@ export default function useCommonEditPageFunctions(dependencies) {
|
|||||||
setWarnUnsavedChanges(autoSaveEnabled);
|
setWarnUnsavedChanges(autoSaveEnabled);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const clearError = ()=>{
|
||||||
|
setError(null);
|
||||||
|
setIsSaving(false);
|
||||||
|
};
|
||||||
|
|
||||||
const trySave = useEffectEvent((forceSave = false, hasChanges = true, saveToGoogle = false)=>{
|
const trySave = useEffectEvent((forceSave = false, hasChanges = true, saveToGoogle = false)=>{
|
||||||
clearTimeout(saveTimeout.current);
|
clearTimeout(saveTimeout.current);
|
||||||
if(isSaving) return;
|
if(isSaving) return;
|
||||||
@@ -140,11 +142,43 @@ export default function useCommonEditPageFunctions(dependencies) {
|
|||||||
}, newTimeout);
|
}, newTimeout);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const renderSaveButton = ()=>{
|
||||||
|
if(isSaving)
|
||||||
|
return <Nav.item className='save' icon='fas fa-spinner fa-spin'>saving...</Nav.item>;
|
||||||
|
|
||||||
|
if(unsavedChanges && warnUnsavedChanges) {
|
||||||
|
resetWarnUnsavedTimer();
|
||||||
|
const elapsedTime = Math.round((new Date() - lastSavedTime) / 1000 / 60);
|
||||||
|
const text = elapsedTime === 0
|
||||||
|
? `Autosave is OFF${sandbox ? ' for this sandbox page' : ''}.`
|
||||||
|
: `Autosave is OFF${sandbox ? ' for this sandbox page' : ''}, 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(unsavedChanges)
|
||||||
|
return <Nav.item className='save' onClick={()=>trySave(true, true, saveGoogle)} color='blue' icon='fas fa-save'>save now</Nav.item>;
|
||||||
|
|
||||||
|
if(autoSaveEnabled)
|
||||||
|
return <Nav.item className='save saved'>auto-saved</Nav.item>;
|
||||||
|
|
||||||
|
if(sandbox)
|
||||||
|
return <Nav.item className='save neverSaved' disabled={true}>save now</Nav.item>;
|
||||||
|
|
||||||
|
return <Nav.item className='save saved'>saved</Nav.item>;
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
resetWarnUnsavedTimer,
|
|
||||||
handleSplitMove,
|
handleSplitMove,
|
||||||
handleBrewChange,
|
handleBrewChange,
|
||||||
toggleAutoSave,
|
toggleAutoSave,
|
||||||
|
clearError,
|
||||||
trySave,
|
trySave,
|
||||||
|
renderSaveButton,
|
||||||
|
autoSaveEnabled,
|
||||||
|
unsavedChanges,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
.note table tbody tr:nth-child(odd) { background : #FFFFFF; }
|
.note table tbody tr:nth-child(odd) { background : #FFFFFF; }
|
||||||
|
|
||||||
/* DROP CAP */
|
/* DROP CAP */
|
||||||
|
.first-letter, .drop-cap
|
||||||
h1 + p::first-letter {
|
h1 + p::first-letter {
|
||||||
color : black;
|
color : black;
|
||||||
background-image : unset;
|
background-image : unset;
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ export default [
|
|||||||
name : 'Tweak Drop Cap',
|
name : 'Tweak Drop Cap',
|
||||||
icon : 'fas fa-sliders-h',
|
icon : 'fas fa-sliders-h',
|
||||||
gen : dedent`/* Drop Cap settings */
|
gen : dedent`/* Drop Cap settings */
|
||||||
|
.page .first-letter, .page .drop-cap,
|
||||||
.page h1 + p::first-letter {
|
.page h1 + p::first-letter {
|
||||||
font-family: SolberaImitationRemake;
|
font-family: SolberaImitationRemake;
|
||||||
font-size: 3.5cm;
|
font-size: 3.5cm;
|
||||||
|
|||||||
+18
-17
@@ -85,23 +85,24 @@
|
|||||||
line-height : 1em;
|
line-height : 1em;
|
||||||
-webkit-column-span : all;
|
-webkit-column-span : all;
|
||||||
-moz-column-span : all;
|
-moz-column-span : all;
|
||||||
& + p::first-letter {
|
|
||||||
float : left;
|
|
||||||
padding-bottom : 2px;
|
|
||||||
padding-left : 40px; //Allow background color to extend into margins
|
|
||||||
margin-top : -0.3cm;
|
|
||||||
margin-bottom : -20px;
|
|
||||||
margin-left : -40px;
|
|
||||||
font-family : 'SolberaImitationRemake';
|
|
||||||
font-size : 3.5cm;
|
|
||||||
line-height : 1em;
|
|
||||||
color : rgba(0, 0, 0, 0);
|
|
||||||
background-image : linear-gradient(-45deg, #322814, #998250, #322814);
|
|
||||||
-webkit-background-clip : text;
|
|
||||||
background-clip : text;
|
|
||||||
}
|
|
||||||
& + p::first-line { font-variant : small-caps; }
|
& + p::first-line { font-variant : small-caps; }
|
||||||
}
|
}
|
||||||
|
.first-letter, .drop-cap,
|
||||||
|
h1 + p::first-letter {
|
||||||
|
float : left;
|
||||||
|
padding-bottom : 2px;
|
||||||
|
padding-left : 40px; //Allow background color to extend into margins
|
||||||
|
margin-top : -0.3cm;
|
||||||
|
margin-bottom : -20px;
|
||||||
|
margin-left : -40px;
|
||||||
|
font-family : 'SolberaImitationRemake';
|
||||||
|
font-size : 3.5cm;
|
||||||
|
line-height : 1em;
|
||||||
|
color : rgba(0, 0, 0, 0);
|
||||||
|
background-image : linear-gradient(-45deg, #322814, #998250, #322814);
|
||||||
|
-webkit-background-clip : text;
|
||||||
|
background-clip : text;
|
||||||
|
}
|
||||||
h2 {
|
h2 {
|
||||||
//margin-top : 0px; //Font is misaligned. Shift up slightly
|
//margin-top : 0px; //Font is misaligned. Shift up slightly
|
||||||
//margin-bottom : 0.05cm;
|
//margin-bottom : 0.05cm;
|
||||||
@@ -196,7 +197,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
& + * { margin-top : 0.54cm; }
|
& + * { margin-top : 0.54cm; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// *****************************
|
// *****************************
|
||||||
@@ -279,7 +280,7 @@
|
|||||||
.watermark { color : black; }
|
.watermark { color : black; }
|
||||||
|
|
||||||
/* Watercolor */
|
/* Watercolor */
|
||||||
|
|
||||||
.watercolor1 { --wc : @watercolor1; }
|
.watercolor1 { --wc : @watercolor1; }
|
||||||
.watercolor2 { --wc : @watercolor2; }
|
.watercolor2 { --wc : @watercolor2; }
|
||||||
.watercolor3 { --wc : @watercolor3; }
|
.watercolor3 { --wc : @watercolor3; }
|
||||||
|
|||||||
@@ -80,21 +80,22 @@
|
|||||||
font-size : 0.89cm;
|
font-size : 0.89cm;
|
||||||
font-variant : small-caps;
|
font-variant : small-caps;
|
||||||
line-height : 1em;
|
line-height : 1em;
|
||||||
& + p::first-letter {
|
|
||||||
float : left;
|
|
||||||
padding-top : 0.3em;
|
|
||||||
padding-bottom : 2px;
|
|
||||||
padding-left : 40px; //Allow background color to extend into margins
|
|
||||||
margin-top : -0.3cm;
|
|
||||||
margin-right : 0.1em;
|
|
||||||
margin-bottom : -20px;
|
|
||||||
margin-left : -40px;
|
|
||||||
font-family : 'FrederickaTheGreat';
|
|
||||||
font-size : 1.9em;
|
|
||||||
line-height : 1em;
|
|
||||||
}
|
|
||||||
& + p::first-line { font-variant : small-caps; }
|
& + p::first-line { font-variant : small-caps; }
|
||||||
}
|
}
|
||||||
|
.first-letter, .drop-cap,
|
||||||
|
h1 + p::first-letter {
|
||||||
|
float : left;
|
||||||
|
padding-top : 0.3em;
|
||||||
|
padding-bottom : 2px;
|
||||||
|
padding-left : 40px; //Allow background color to extend into margins
|
||||||
|
margin-top : -0.3cm;
|
||||||
|
margin-right : 0.1em;
|
||||||
|
margin-bottom : -20px;
|
||||||
|
margin-left : -40px;
|
||||||
|
font-family : 'FrederickaTheGreat';
|
||||||
|
font-size : 1.9em;
|
||||||
|
line-height : 1em;
|
||||||
|
}
|
||||||
h2 {
|
h2 {
|
||||||
font-size : 0.62cm;
|
font-size : 0.62cm;
|
||||||
line-height : 0.988em; //Font is misaligned. Shift up slightly
|
line-height : 0.988em; //Font is misaligned. Shift up slightly
|
||||||
|
|||||||
Reference in New Issue
Block a user