0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2026-01-26 22:43:07 +00:00

Compare commits

..

2 Commits

Author SHA1 Message Date
Trevor Buckner
943036723a Merge branch 'master' into dependabot/npm_and_yarn/dev-dependencies-65f50cb316 2025-11-09 18:59:17 -05:00
dependabot[bot]
bef46997ed Bump eslint from 9.39.0 to 9.39.1 in the dev-dependencies group
Bumps the dev-dependencies group with 1 update: [eslint](https://github.com/eslint/eslint).


Updates `eslint` from 9.39.0 to 9.39.1
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/compare/v9.39.0...v9.39.1)

---
updated-dependencies:
- dependency-name: eslint
  dependency-version: 9.39.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-09 23:30:26 +00:00
113 changed files with 5189 additions and 5248 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
import './admin.less'; import './admin.less';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import BrewUtils from './brewUtils/brewUtils.jsx'; const BrewUtils = require('./brewUtils/brewUtils.jsx');
import NotificationUtils from './notificationUtils/notificationUtils.jsx'; const NotificationUtils = require('./notificationUtils/notificationUtils.jsx');
import AuthorUtils from './authorUtils/authorUtils.jsx'; import AuthorUtils from './authorUtils/authorUtils.jsx';
import LockTools from './lockTools/lockTools.jsx'; import LockTools from './lockTools/lockTools.jsx';

View File

@@ -84,4 +84,4 @@ const authorLookup = ()=>{
); );
}; };
export default authorLookup; module.exports = authorLookup;

View File

@@ -10,4 +10,4 @@ const authorUtils = ()=>{
); );
}; };
export default authorUtils; module.exports = authorUtils;

View File

@@ -1,8 +1,9 @@
import React from 'react'; const React = require('react');
import createReactClass from 'create-react-class'; const createClass = require('create-react-class');
import request from 'superagent';
const BrewCleanup = createReactClass({ const request = require('superagent');
const BrewCleanup = createClass({
displayName : 'BrewCleanup', displayName : 'BrewCleanup',
getDefaultProps(){ getDefaultProps(){
return {}; return {};
@@ -68,4 +69,4 @@ const BrewCleanup = createReactClass({
} }
}); });
export default BrewCleanup; module.exports = BrewCleanup;

View File

@@ -1,8 +1,8 @@
import React from 'react'; const React = require('react');
import createReactClass from 'create-react-class'; const createClass = require('create-react-class');
import request from 'superagent'; const request = require('superagent');
const BrewCompress = createReactClass({ const BrewCompress = createClass({
displayName : 'BrewCompress', displayName : 'BrewCompress',
getDefaultProps(){ getDefaultProps(){
return {}; return {};
@@ -85,4 +85,4 @@ const BrewCompress = createReactClass({
} }
}); });
export default BrewCompress; module.exports = BrewCompress;

View File

@@ -1,11 +1,12 @@
import React from 'react'; const React = require('react');
import createReactClass from 'create-react-class'; const createClass = require('create-react-class');
import request from 'superagent'; const cx = require('classnames');
import cx from 'classnames';
import Moment from 'moment'; const request = require('superagent');
const Moment = require('moment');
const BrewLookup = createReactClass({
const BrewLookup = createClass({
getDefaultProps() { getDefaultProps() {
return {}; return {};
}, },
@@ -109,4 +110,4 @@ const BrewLookup = createReactClass({
} }
}); });
export default BrewLookup; module.exports = BrewLookup;

View File

@@ -1,14 +1,15 @@
import React from 'react'; const React = require('react');
import './brewUtils.less'; const createClass = require('create-react-class');
require('./brewUtils.less');
import BrewCleanup from './brewCleanup/brewCleanup.jsx'; const BrewCleanup = require('./brewCleanup/brewCleanup.jsx');
import BrewLookup from './brewLookup/brewLookup.jsx'; const BrewLookup = require('./brewLookup/brewLookup.jsx');
import BrewCompress from './brewCompress/brewCompress.jsx'; const BrewCompress = require ('./brewCompress/brewCompress.jsx');
import Stats from './stats/stats.jsx'; const Stats = require('./stats/stats.jsx');
const BrewUtils = ()=>{ const BrewUtils = createClass({
return ( render : function(){
<> return <>
<Stats /> <Stats />
<hr /> <hr />
<BrewLookup /> <BrewLookup />
@@ -16,7 +17,8 @@ const BrewUtils = ()=>{
<BrewCleanup /> <BrewCleanup />
<hr /> <hr />
<BrewCompress /> <BrewCompress />
</> </>;
); }
}; });
export default BrewUtils;
module.exports = BrewUtils;

View File

@@ -1,8 +1,9 @@
import React from 'react'; const React = require('react');
import createReactClass from 'create-react-class'; const createClass = require('create-react-class');
import request from 'superagent';
const Stats = createReactClass({ const request = require('superagent');
const Stats = createClass({
displayName : 'Stats', displayName : 'Stats',
getDefaultProps(){ getDefaultProps(){
return {}; return {};
@@ -42,4 +43,4 @@ const Stats = createReactClass({
} }
}); });
export default Stats; module.exports = Stats;

View File

@@ -1,11 +1,11 @@
/*eslint max-lines: ["warn", {"max": 500, "skipBlankLines": true, "skipComments": true}]*/ /*eslint max-lines: ["warn", {"max": 500, "skipBlankLines": true, "skipComments": true}]*/
import './lockTools.less'; require('./lockTools.less');
import React from 'react'; const React = require('react');
import createReactClass from 'create-react-class'; const createClass = require('create-react-class');
import request from '../../homebrew/utils/request-middleware.js'; import request from '../../homebrew/utils/request-middleware.js';
const LockTools = createReactClass({ const LockTools = createClass({
displayName : 'LockTools', displayName : 'LockTools',
getInitialState : function() { getInitialState : function() {
return { return {
@@ -55,7 +55,7 @@ const LockTools = createReactClass({
} }
}); });
const LockBrew = createReactClass({ const LockBrew = createClass({
displayName : 'LockBrew', displayName : 'LockBrew',
getInitialState : function() { getInitialState : function() {
// Default values // Default values
@@ -183,7 +183,7 @@ const LockBrew = createReactClass({
} }
}); });
const LockTable = createReactClass({ const LockTable = createClass({
displayName : 'LockTable', displayName : 'LockTable',
getDefaultProps : function() { getDefaultProps : function() {
return { return {
@@ -273,7 +273,7 @@ const LockTable = createReactClass({
} }
}); });
const LockLookup = createReactClass({ const LockLookup = createClass({
displayName : 'LockLookup', displayName : 'LockLookup',
getDefaultProps : function() { getDefaultProps : function() {
return { return {
@@ -339,4 +339,4 @@ const LockLookup = createReactClass({
} }
}); });
export default LockTools; module.exports = LockTools;

View File

@@ -1,6 +1,7 @@
import './notificationAdd.less'; require('./notificationAdd.less');
import React, { useState, useRef } from 'react'; const React = require('react');
import request from 'superagent'; const { useState, useRef } = require('react');
const request = require('superagent');
const NotificationAdd = ()=>{ const NotificationAdd = ()=>{
const [notificationResult, setNotificationResult] = useState(null); const [notificationResult, setNotificationResult] = useState(null);
@@ -105,4 +106,4 @@ const NotificationAdd = ()=>{
); );
}; };
export default NotificationAdd; module.exports = NotificationAdd;

View File

@@ -1,7 +1,9 @@
import './notificationLookup.less'; require('./notificationLookup.less');
import React, { useState } from 'react';
import request from 'superagent'; const React = require('react');
import Moment from 'moment'; const { useState } = require('react');
const request = require('superagent');
const Moment = require('moment');
const NotificationDetail = ({ notification, onDelete })=>( const NotificationDetail = ({ notification, onDelete })=>(
<> <>
@@ -100,4 +102,4 @@ const NotificationLookup = ()=>{
); );
}; };
export default NotificationLookup; module.exports = NotificationLookup;

View File

@@ -1,6 +1,7 @@
import React from 'react'; const React = require('react');
import NotificationLookup from './notificationLookup/notificationLookup.jsx';
import NotificationAdd from './notificationAdd/notificationAdd.jsx'; const NotificationLookup = require('./notificationLookup/notificationLookup.jsx');
const NotificationAdd = require('./notificationAdd/notificationAdd.jsx');
const NotificationUtils = ()=>{ const NotificationUtils = ()=>{
return ( return (
@@ -11,4 +12,4 @@ const NotificationUtils = ()=>{
); );
}; };
export default NotificationUtils; module.exports = NotificationUtils;

View File

@@ -1,9 +1,9 @@
import React from 'react'; const React = require('react');
import createReactClass from 'create-react-class'; const createClass = require('create-react-class');
import _ from 'lodash'; const _ = require('lodash');
import './combobox.less'; require('./combobox.less');
const Combobox = createReactClass({ const Combobox = createClass({
displayName : 'Combobox', displayName : 'Combobox',
getDefaultProps : function() { getDefaultProps : function() {
return { return {
@@ -126,4 +126,4 @@ const Combobox = createReactClass({
} }
}); });
export default Combobox; module.exports = Combobox;

View File

@@ -1,11 +1,11 @@
import './renderWarnings.less'; require('./renderWarnings.less');
import React from 'react'; const React = require('react');
import createReactClass from 'create-react-class'; const createClass = require('create-react-class');
import _ from 'lodash'; const _ = require('lodash');
import Dialog from '../dialog.jsx'; import Dialog from '../dialog.jsx';
const RenderWarnings = createReactClass({ const RenderWarnings = createClass({
displayName : 'RenderWarnings', displayName : 'RenderWarnings',
getInitialState : function() { getInitialState : function() {
return { return {
@@ -57,4 +57,4 @@ const RenderWarnings = createReactClass({
} }
}); });
export default RenderWarnings; module.exports = RenderWarnings;

View File

@@ -1,5 +1,6 @@
import './splitPane.less'; require('./splitPane.less');
import React, { useEffect, useState } from 'react'; const React = require('react');
const { useState, useEffect } = React;
const PANE_WIDTH_KEY = 'HB_editor_splitWidth'; const PANE_WIDTH_KEY = 'HB_editor_splitWidth';
const LIVE_SCROLL_KEY = 'HB_editor_liveScroll'; const LIVE_SCROLL_KEY = 'HB_editor_liveScroll';
@@ -107,4 +108,4 @@ const Pane = ({ width, children, isDragging, moveBrew, moveSource, liveScroll, s
); );
}; };
export default SplitPane; module.exports = SplitPane;

View File

@@ -1,6 +1,7 @@
import React from 'react'; const React = require('react');
const createClass = require('create-react-class');
export default function(props){ module.exports = function(props){
return <svg version='1.1' x='0px' y='0px' viewBox='0 0 90 112.5' enableBackground='new 0 0 90 90' > return <svg version='1.1' x='0px' y='0px' viewBox='0 0 90 112.5' enableBackground='new 0 0 90 90' >
<path d='M25.363,25.54c0,1.906,8.793,3.454,19.636,3.454c10.848,0,19.638-1.547,19.638-3.454c0-1.12-3.056-2.117-7.774-2.75 c-1.418,1.891-3.659,3.133-6.208,3.133c-2.85,0-5.315-1.547-6.67-3.833C33.617,22.185,25.363,23.692,25.363,25.54z'/><path d='M84.075,54.142c0-8.68-2.868-17.005-8.144-23.829c1.106-1.399,1.41-2.771,1.41-3.854c0-6.574-10.245-9.358-19.264-10.533 c0.209,0.706,0.359,1.439,0.359,2.215c0,0.09-0.022,0.17-0.028,0.26l0,0c-0.028,0.853-0.195,1.667-0.479,2.429 c9.106,1.282,14.508,3.754,14.508,5.63c0,2.644-10.688,6.486-27.439,6.486c-16.748,0-27.438-3.842-27.438-6.486 c0-2.542,9.904-6.183,25.559-6.459c-0.098-0.396-0.159-0.807-0.2-1.223c0.006,0,0.013,0,0.017,0 c-0.017-0.213-0.063-0.417-0.063-0.636c0-1.084,0.226-2.119,0.628-3.058c-6.788,0.129-30.846,1.299-30.846,11.376 c0,1.083,0.305,2.455,1.411,3.854c-5.276,6.823-8.145,15.149-8.145,23.829c0,11.548,5.187,20.107,14.693,25.115 c-0.902,3.146-1.391,7.056,1.111,8.181c2.626,1.178,5.364-2.139,7.111-5.005c4.73,1.261,10.13,1.923,16.161,1.923 c6.034,0,11.428-0.661,16.158-1.922c1.75,2.865,4.493,6.18,7.112,5.004c2.504-1.123,2.014-5.035,1.113-8.179 C78.889,74.249,84.075,65.689,84.075,54.142z M70.39,31.392c5.43,6.046,8.78,14,8.78,22.75c0,20.919-18.582,25.309-34.171,25.309 c-15.587,0-34.17-4.39-34.17-25.309c0-8.75,3.35-16.7,8.781-22.753c5.561,2.643,15.502,4.009,25.389,4.009 C54.886,35.397,64.829,34.031,70.39,31.392z'/><path d='M50.654,23.374c2.892,0,5.234-2.341,5.234-5.233c0-2.887-2.343-5.23-5.234-5.23c-2.887,0-5.231,2.343-5.231,5.23 C45.423,21.032,47.768,23.374,50.654,23.374z'/> <path d='M25.363,25.54c0,1.906,8.793,3.454,19.636,3.454c10.848,0,19.638-1.547,19.638-3.454c0-1.12-3.056-2.117-7.774-2.75 c-1.418,1.891-3.659,3.133-6.208,3.133c-2.85,0-5.315-1.547-6.67-3.833C33.617,22.185,25.363,23.692,25.363,25.54z'/><path d='M84.075,54.142c0-8.68-2.868-17.005-8.144-23.829c1.106-1.399,1.41-2.771,1.41-3.854c0-6.574-10.245-9.358-19.264-10.533 c0.209,0.706,0.359,1.439,0.359,2.215c0,0.09-0.022,0.17-0.028,0.26l0,0c-0.028,0.853-0.195,1.667-0.479,2.429 c9.106,1.282,14.508,3.754,14.508,5.63c0,2.644-10.688,6.486-27.439,6.486c-16.748,0-27.438-3.842-27.438-6.486 c0-2.542,9.904-6.183,25.559-6.459c-0.098-0.396-0.159-0.807-0.2-1.223c0.006,0,0.013,0,0.017,0 c-0.017-0.213-0.063-0.417-0.063-0.636c0-1.084,0.226-2.119,0.628-3.058c-6.788,0.129-30.846,1.299-30.846,11.376 c0,1.083,0.305,2.455,1.411,3.854c-5.276,6.823-8.145,15.149-8.145,23.829c0,11.548,5.187,20.107,14.693,25.115 c-0.902,3.146-1.391,7.056,1.111,8.181c2.626,1.178,5.364-2.139,7.111-5.005c4.73,1.261,10.13,1.923,16.161,1.923 c6.034,0,11.428-0.661,16.158-1.922c1.75,2.865,4.493,6.18,7.112,5.004c2.504-1.123,2.014-5.035,1.113-8.179 C78.889,74.249,84.075,65.689,84.075,54.142z M70.39,31.392c5.43,6.046,8.78,14,8.78,22.75c0,20.919-18.582,25.309-34.171,25.309 c-15.587,0-34.17-4.39-34.17-25.309c0-8.75,3.35-16.7,8.781-22.753c5.561,2.643,15.502,4.009,25.389,4.009 C54.886,35.397,64.829,34.031,70.39,31.392z'/><path d='M50.654,23.374c2.892,0,5.234-2.341,5.234-5.233c0-2.887-2.343-5.23-5.234-5.23c-2.887,0-5.231,2.343-5.231,5.23 C45.423,21.032,47.768,23.374,50.654,23.374z'/>
<circle cx='62.905' cy='10.089' r='3.595'/> <circle cx='62.905' cy='10.089' r='3.595'/>

View File

@@ -1,5 +1,6 @@
import React from 'react'; const React = require('react');
const createClass = require('create-react-class');
export default function(props){ module.exports = function(props){
return <svg version='1.1' x='0px' y='0px' viewBox='0 0 100 100' enableBackground='new 0 0 100 100'><path d='M80.644,87.982l16.592-41.483c0.054-0.128,0.088-0.26,0.108-0.394c0.006-0.039,0.007-0.077,0.011-0.116 c0.007-0.087,0.008-0.174,0.002-0.26c-0.003-0.046-0.007-0.091-0.014-0.137c-0.014-0.089-0.036-0.176-0.063-0.262 c-0.012-0.034-0.019-0.069-0.031-0.103c-0.047-0.118-0.106-0.229-0.178-0.335c-0.004-0.006-0.006-0.012-0.01-0.018L67.999,3.358 c-0.01-0.013-0.003-0.026-0.013-0.04L68,3.315V4c0,0-0.033,0-0.037,0c-0.403-1-1.094-1.124-1.752-0.976 c0,0.004-0.004-0.012-0.007-0.012C66.201,3.016,66.194,3,66.194,3H66.19h-0.003h-0.003h-0.004h-0.003c0,0-0.004,0-0.007,0 s-0.003-0.151-0.007-0.151L20.495,15.227c-0.025,0.007-0.046-0.019-0.071-0.011c-0.087,0.028-0.172,0.041-0.253,0.083 c-0.054,0.027-0.102,0.053-0.152,0.085c-0.051,0.033-0.101,0.061-0.147,0.099c-0.044,0.036-0.084,0.073-0.124,0.113 c-0.048,0.048-0.093,0.098-0.136,0.152c-0.03,0.039-0.059,0.076-0.085,0.117c-0.046,0.07-0.084,0.145-0.12,0.223 c-0.011,0.023-0.027,0.042-0.036,0.066L2.911,57.664C2.891,57.715,3,57.768,3,57.82v0.002c0,0.186,0,0.375,0,0.562 c0,0.004,0,0.004,0,0.008c0,0,0,0,0,0.002c0,0,0,0,0,0.004v0.004v0.002c0,0.074-0.002,0.15,0.012,0.223 C3.015,58.631,3,58.631,3,58.633c0,0.004,0,0.004,0,0.008c0,0,0,0,0,0.002c0,0,0,0,0,0.004v0.004c0,0,0,0,0,0.002v0.004 c0,0.191-0.046,0.377,0.06,0.545c0-0.002-0.03,0.004-0.03,0.004c0,0.004-0.03,0.004-0.03,0.004c0,0.002,0,0.002,0,0.002 l-0.045,0.004c0.03,0.047,0.036,0.09,0.068,0.133l29.049,37.359c0.002,0.004,0,0.006,0.002,0.01c0.002,0.002,0,0.004,0.002,0.008 c0.006,0.008,0.014,0.014,0.021,0.021c0.024,0.029,0.052,0.051,0.078,0.078c0.027,0.029,0.053,0.057,0.082,0.082 c0.03,0.027,0.055,0.062,0.086,0.088c0.026,0.02,0.057,0.033,0.084,0.053c0.04,0.027,0.081,0.053,0.123,0.076 c0.005,0.004,0.01,0.008,0.016,0.01c0.087,0.051,0.176,0.09,0.269,0.123c0.042,0.014,0.082,0.031,0.125,0.043 c0.021,0.006,0.041,0.018,0.062,0.021c0.123,0.027,0.249,0.043,0.375,0.043c0.099,0,0.202-0.012,0.304-0.027l45.669-8.303 c0.057-0.01,0.108-0.021,0.163-0.037C79.547,88.992,79.562,89,79.575,89c0.004,0,0.004,0,0.004,0c0.021,0,0.039-0.027,0.06-0.035 c0.041-0.014,0.08-0.034,0.12-0.052c0.021-0.01,0.044-0.019,0.064-0.03c0.017-0.01,0.026-0.015,0.033-0.017 c0.014-0.008,0.023-0.021,0.037-0.028c0.14-0.078,0.269-0.174,0.38-0.285c0.014-0.016,0.024-0.034,0.038-0.048 c0.109-0.119,0.201-0.252,0.271-0.398c0.006-0.01,0.016-0.018,0.021-0.029c0.004-0.008,0.008-0.017,0.011-0.026 c0.002-0.004,0.003-0.006,0.005-0.01C80.627,88.021,80.635,88.002,80.644,87.982z M77.611,84.461L48.805,66.453l32.407-25.202 L77.611,84.461z M46.817,63.709L35.863,23.542l43.818,14.608L46.817,63.709z M84.668,40.542l8.926,5.952l-11.902,29.75 L84.668,40.542z M89.128,39.446L84.53,36.38l-6.129-12.257L89.128,39.446z M79.876,34.645L37.807,20.622L65.854,6.599L79.876,34.645 z M33.268,19.107l-6.485-2.162l23.781-6.487L33.268,19.107z M21.92,18.895l8.67,2.891L10.357,47.798L21.92,18.895z M32.652,24.649 l10.845,39.757L7.351,57.178L32.652,24.649z M43.472,67.857L32.969,92.363L8.462,60.855L43.472,67.857z M46.631,69.09l27.826,17.393 l-38.263,6.959L46.631,69.09z'></path></svg>; return <svg version='1.1' x='0px' y='0px' viewBox='0 0 100 100' enableBackground='new 0 0 100 100'><path d='M80.644,87.982l16.592-41.483c0.054-0.128,0.088-0.26,0.108-0.394c0.006-0.039,0.007-0.077,0.011-0.116 c0.007-0.087,0.008-0.174,0.002-0.26c-0.003-0.046-0.007-0.091-0.014-0.137c-0.014-0.089-0.036-0.176-0.063-0.262 c-0.012-0.034-0.019-0.069-0.031-0.103c-0.047-0.118-0.106-0.229-0.178-0.335c-0.004-0.006-0.006-0.012-0.01-0.018L67.999,3.358 c-0.01-0.013-0.003-0.026-0.013-0.04L68,3.315V4c0,0-0.033,0-0.037,0c-0.403-1-1.094-1.124-1.752-0.976 c0,0.004-0.004-0.012-0.007-0.012C66.201,3.016,66.194,3,66.194,3H66.19h-0.003h-0.003h-0.004h-0.003c0,0-0.004,0-0.007,0 s-0.003-0.151-0.007-0.151L20.495,15.227c-0.025,0.007-0.046-0.019-0.071-0.011c-0.087,0.028-0.172,0.041-0.253,0.083 c-0.054,0.027-0.102,0.053-0.152,0.085c-0.051,0.033-0.101,0.061-0.147,0.099c-0.044,0.036-0.084,0.073-0.124,0.113 c-0.048,0.048-0.093,0.098-0.136,0.152c-0.03,0.039-0.059,0.076-0.085,0.117c-0.046,0.07-0.084,0.145-0.12,0.223 c-0.011,0.023-0.027,0.042-0.036,0.066L2.911,57.664C2.891,57.715,3,57.768,3,57.82v0.002c0,0.186,0,0.375,0,0.562 c0,0.004,0,0.004,0,0.008c0,0,0,0,0,0.002c0,0,0,0,0,0.004v0.004v0.002c0,0.074-0.002,0.15,0.012,0.223 C3.015,58.631,3,58.631,3,58.633c0,0.004,0,0.004,0,0.008c0,0,0,0,0,0.002c0,0,0,0,0,0.004v0.004c0,0,0,0,0,0.002v0.004 c0,0.191-0.046,0.377,0.06,0.545c0-0.002-0.03,0.004-0.03,0.004c0,0.004-0.03,0.004-0.03,0.004c0,0.002,0,0.002,0,0.002 l-0.045,0.004c0.03,0.047,0.036,0.09,0.068,0.133l29.049,37.359c0.002,0.004,0,0.006,0.002,0.01c0.002,0.002,0,0.004,0.002,0.008 c0.006,0.008,0.014,0.014,0.021,0.021c0.024,0.029,0.052,0.051,0.078,0.078c0.027,0.029,0.053,0.057,0.082,0.082 c0.03,0.027,0.055,0.062,0.086,0.088c0.026,0.02,0.057,0.033,0.084,0.053c0.04,0.027,0.081,0.053,0.123,0.076 c0.005,0.004,0.01,0.008,0.016,0.01c0.087,0.051,0.176,0.09,0.269,0.123c0.042,0.014,0.082,0.031,0.125,0.043 c0.021,0.006,0.041,0.018,0.062,0.021c0.123,0.027,0.249,0.043,0.375,0.043c0.099,0,0.202-0.012,0.304-0.027l45.669-8.303 c0.057-0.01,0.108-0.021,0.163-0.037C79.547,88.992,79.562,89,79.575,89c0.004,0,0.004,0,0.004,0c0.021,0,0.039-0.027,0.06-0.035 c0.041-0.014,0.08-0.034,0.12-0.052c0.021-0.01,0.044-0.019,0.064-0.03c0.017-0.01,0.026-0.015,0.033-0.017 c0.014-0.008,0.023-0.021,0.037-0.028c0.14-0.078,0.269-0.174,0.38-0.285c0.014-0.016,0.024-0.034,0.038-0.048 c0.109-0.119,0.201-0.252,0.271-0.398c0.006-0.01,0.016-0.018,0.021-0.029c0.004-0.008,0.008-0.017,0.011-0.026 c0.002-0.004,0.003-0.006,0.005-0.01C80.627,88.021,80.635,88.002,80.644,87.982z M77.611,84.461L48.805,66.453l32.407-25.202 L77.611,84.461z M46.817,63.709L35.863,23.542l43.818,14.608L46.817,63.709z M84.668,40.542l8.926,5.952l-11.902,29.75 L84.668,40.542z M89.128,39.446L84.53,36.38l-6.129-12.257L89.128,39.446z M79.876,34.645L37.807,20.622L65.854,6.599L79.876,34.645 z M33.268,19.107l-6.485-2.162l23.781-6.487L33.268,19.107z M21.92,18.895l8.67,2.891L10.357,47.798L21.92,18.895z M32.652,24.649 l10.845,39.757L7.351,57.178L32.652,24.649z M43.472,67.857L32.969,92.363L8.462,60.855L43.472,67.857z M46.631,69.09l27.826,17.393 l-38.263,6.959L46.631,69.09z'></path></svg>;
}; };

View File

@@ -1,19 +1,20 @@
/*eslint max-lines: ["warn", {"max": 300, "skipBlankLines": true, "skipComments": true}]*/ /*eslint max-lines: ["warn", {"max": 300, "skipBlankLines": true, "skipComments": true}]*/
import './brewRenderer.less'; require('./brewRenderer.less');
import React, { useState, useRef, useMemo, useEffect } from 'react'; const React = require('react');
import _ from 'lodash'; const { useState, useRef, useMemo, useEffect } = React;
const _ = require('lodash');
import MarkdownLegacy from '../../../shared/markdownLegacy.js'; const MarkdownLegacy = require('markdownLegacy.js');
import Markdown from '../../../shared/markdown.js'; import Markdown from 'markdown.js';
import ErrorBar from './errorBar/errorBar.jsx'; const ErrorBar = require('./errorBar/errorBar.jsx');
import ToolBar from './toolBar/toolBar.jsx'; const ToolBar = require('./toolBar/toolBar.jsx');
//TODO: move to the brew renderer //TODO: move to the brew renderer
import RenderWarnings from '../../components/renderWarnings/renderWarnings.jsx'; const RenderWarnings = require('client/components/renderWarnings/renderWarnings.jsx');
import NotificationPopup from './notificationPopup/notificationPopup.jsx'; const NotificationPopup = require('./notificationPopup/notificationPopup.jsx');
import Frame from 'react-frame-component'; const Frame = require('react-frame-component').default;
import dedent from 'dedent'; const dedent = require('dedent-tabs').default;
import { printCurrentBrew } from '../../../shared/helpers.js'; const { printCurrentBrew } = require('../../../shared/helpers.js');
import HeaderNav from './headerNav/headerNav.jsx'; import HeaderNav from './headerNav/headerNav.jsx';
import { safeHTML } from './safeHTML.js'; import { safeHTML } from './safeHTML.js';
@@ -344,4 +345,4 @@ const BrewRenderer = (props)=>{
); );
}; };
export default BrewRenderer; module.exports = BrewRenderer;

View File

@@ -1,5 +1,5 @@
import './errorBar.less'; require('./errorBar.less');
import React from 'react'; const React = require('react');
import Dialog from '../../../components/dialog.jsx'; import Dialog from '../../../components/dialog.jsx';
@@ -50,4 +50,4 @@ const ErrorBar = (props)=>{
); );
}; };
export default ErrorBar; module.exports = ErrorBar;

View File

@@ -1,7 +1,7 @@
import './headerNav.less'; require('./headerNav.less');
import React from 'react'; import * as React from 'react';
import _ from 'lodash'; import * as _ from 'lodash';
const MAX_TEXT_LENGTH = 40; const MAX_TEXT_LENGTH = 40;

View File

@@ -1,4 +1,4 @@
import './notificationPopup.less'; require('./notificationPopup.less');
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import request from '../../utils/request-middleware.js'; import request from '../../utils/request-middleware.js';
import Markdown from 'markdown.js'; import Markdown from 'markdown.js';
@@ -62,4 +62,4 @@ const NotificationPopup = ()=>{
</Dialog>; </Dialog>;
}; };
export default NotificationPopup; module.exports = NotificationPopup;

View File

@@ -1,7 +1,8 @@
/* eslint-disable max-lines */ /* eslint-disable max-lines */
import './toolBar.less'; require('./toolBar.less');
import React, { useState, useEffect } from 'react'; const React = require('react');
import _ from 'lodash'; const { useState, useEffect } = React;
const _ = require('lodash');
import { Anchored, AnchoredBox, AnchoredTrigger } from '../../../components/Anchored.jsx'; import { Anchored, AnchoredBox, AnchoredTrigger } from '../../../components/Anchored.jsx';
@@ -258,4 +259,4 @@ const ToolBar = ({ displayOptions, onDisplayOptionsChange, visiblePages, totalPa
); );
}; };
export default ToolBar; module.exports = ToolBar;

View File

@@ -1,14 +1,14 @@
/*eslint max-lines: ["warn", {"max": 500, "skipBlankLines": true, "skipComments": true}]*/ /*eslint max-lines: ["warn", {"max": 500, "skipBlankLines": true, "skipComments": true}]*/
import './editor.less'; require('./editor.less');
import React from 'react'; const React = require('react');
import createReactClass from 'create-react-class'; const createClass = require('create-react-class');
import _ from 'lodash'; const _ = require('lodash');
import dedent from 'dedent'; const dedent = require('dedent-tabs').default;
import Markdown from '../../../shared/markdown.js'; import Markdown from '../../../shared/markdown.js';
import CodeEditor from '../../components/codeEditor/codeEditor.jsx'; const CodeEditor = require('naturalcrit/codeEditor/codeEditor.jsx');
import SnippetBar from './snippetbar/snippetbar.jsx'; const SnippetBar = require('./snippetbar/snippetbar.jsx');
import MetadataEditor from './metadataEditor/metadataEditor.jsx'; const MetadataEditor = require('./metadataEditor/metadataEditor.jsx');
const EDITOR_THEME_KEY = 'HB_editor_theme'; const EDITOR_THEME_KEY = 'HB_editor_theme';
@@ -31,7 +31,7 @@ const DEFAULT_SNIPPET_TEXT = dedent`
`; `;
let isJumping = false; let isJumping = false;
const Editor = createReactClass({ const Editor = createClass({
displayName : 'Editor', displayName : 'Editor',
getDefaultProps : function() { getDefaultProps : function() {
return { return {
@@ -58,7 +58,7 @@ const Editor = createReactClass({
return { return {
editorTheme : this.props.editorTheme, editorTheme : this.props.editorTheme,
view : 'text', //'text', 'style', 'meta', 'snippet' view : 'text', //'text', 'style', 'meta', 'snippet'
snippetBarHeight : 26, snippetbarHeight : 25
}; };
}, },
@@ -76,8 +76,8 @@ const Editor = createReactClass({
document.getElementById('BrewRenderer').addEventListener('keydown', this.handleControlKeys); document.getElementById('BrewRenderer').addEventListener('keydown', this.handleControlKeys);
document.addEventListener('keydown', this.handleControlKeys); document.addEventListener('keydown', this.handleControlKeys);
this.codeEditor.current.codeMirror?.on('cursorActivity', (cm)=>{this.updateCurrentCursorPage(cm.getCursor());}); this.codeEditor.current.codeMirror.on('cursorActivity', (cm)=>{this.updateCurrentCursorPage(cm.getCursor());});
this.codeEditor.current.codeMirror?.on('scroll', _.throttle(()=>{this.updateCurrentViewPage(this.codeEditor.current.getTopVisibleLine());}, 200)); this.codeEditor.current.codeMirror.on('scroll', _.throttle(()=>{this.updateCurrentViewPage(this.codeEditor.current.getTopVisibleLine());}, 200));
const editorTheme = window.localStorage.getItem(EDITOR_THEME_KEY); const editorTheme = window.localStorage.getItem(EDITOR_THEME_KEY);
if(editorTheme) { if(editorTheme) {
@@ -85,15 +85,7 @@ const Editor = createReactClass({
editorTheme : editorTheme editorTheme : editorTheme
}); });
} }
const snippetBar = document.querySelector('.editor > .snippetBar'); this.setState({ snippetbarHeight: document.querySelector('.editor > .snippetBar').offsetHeight });
if (!snippetBar) return;
this.resizeObserver = new ResizeObserver(entries => {
const height = document.querySelector('.editor > .snippetBar').offsetHeight;
this.setState({ snippetBarHeight: height });
});
this.resizeObserver.observe(snippetBar);
}, },
componentDidUpdate : function(prevProps, prevState, snapshot) { componentDidUpdate : function(prevProps, prevState, snapshot) {
@@ -116,10 +108,6 @@ const Editor = createReactClass({
} }
}, },
componentWillUnmount() {
if (this.resizeObserver) this.resizeObserver.disconnect();
},
handleControlKeys : function(e){ handleControlKeys : function(e){
if(!(e.ctrlKey && e.metaKey && e.shiftKey)) return; if(!(e.ctrlKey && e.metaKey && e.shiftKey)) return;
const LEFTARROW_KEY = 37; const LEFTARROW_KEY = 37;
@@ -156,21 +144,21 @@ const Editor = createReactClass({
this.setState({ this.setState({
view : newView view : newView
}, ()=>{ }, ()=>{
this.codeEditor.current?.codeMirror?.focus(); this.codeEditor.current?.codeMirror.focus();
}); });
}, },
highlightCustomMarkdown : function(){ highlightCustomMarkdown : function(){
if(!this.codeEditor.current?.codeMirror) return; if(!this.codeEditor.current) return;
if((this.state.view === 'text') ||(this.state.view === 'snippet')) { if((this.state.view === 'text') ||(this.state.view === 'snippet')) {
const codeMirror = this.codeEditor.current.codeMirror; const codeMirror = this.codeEditor.current.codeMirror;
codeMirror?.operation(()=>{ // Batch CodeMirror styling codeMirror.operation(()=>{ // Batch CodeMirror styling
const foldLines = []; const foldLines = [];
//reset custom text styles //reset custom text styles
const customHighlights = codeMirror?.getAllMarks().filter((mark)=>{ const customHighlights = codeMirror.getAllMarks().filter((mark)=>{
// Record details of folded sections // Record details of folded sections
if(mark.__isFold) { if(mark.__isFold) {
const fold = mark.find(); const fold = mark.find();
@@ -191,10 +179,10 @@ const Editor = createReactClass({
const textOrSnip = this.state.view === 'text'; const textOrSnip = this.state.view === 'text';
//reset custom line styles //reset custom line styles
codeMirror?.removeLineClass(lineNumber, 'background', 'pageLine'); codeMirror.removeLineClass(lineNumber, 'background', 'pageLine');
codeMirror?.removeLineClass(lineNumber, 'background', 'snippetLine'); codeMirror.removeLineClass(lineNumber, 'background', 'snippetLine');
codeMirror?.removeLineClass(lineNumber, 'text'); codeMirror.removeLineClass(lineNumber, 'text');
codeMirror?.removeLineClass(lineNumber, 'wrap', 'sourceMoveFlash'); codeMirror.removeLineClass(lineNumber, 'wrap', 'sourceMoveFlash');
// Don't process lines inside folded text // Don't process lines inside folded text
// If the current lineNumber is inside any folded marks, skip line styling // If the current lineNumber is inside any folded marks, skip line styling
@@ -210,19 +198,19 @@ const Editor = createReactClass({
else if(this.state.view !== 'text') userSnippetCount += 1; else if(this.state.view !== 'text') userSnippetCount += 1;
// add back the original class 'background' but also add the new class '.pageline' // add back the original class 'background' but also add the new class '.pageline'
codeMirror?.addLineClass(lineNumber, 'background', tabHighlight); codeMirror.addLineClass(lineNumber, 'background', tabHighlight);
const pageCountElement = Object.assign(document.createElement('span'), { const pageCountElement = Object.assign(document.createElement('span'), {
className : 'editor-page-count', className : 'editor-page-count',
textContent : textOrSnip ? editorPageCount : userSnippetCount textContent : textOrSnip ? editorPageCount : userSnippetCount
}); });
codeMirror?.setBookmark({ line: lineNumber, ch: line.length }, pageCountElement); codeMirror.setBookmark({ line: lineNumber, ch: line.length }, pageCountElement);
}; };
// New CodeMirror styling for V3 renderer // New Codemirror styling for V3 renderer
if(this.props.renderer === 'V3') { if(this.props.renderer === 'V3') {
if(line.match(/^\\column(?:break)?$/)){ if(line.match(/^\\column(?:break)?$/)){
codeMirror?.addLineClass(lineNumber, 'text', 'columnSplit'); codeMirror.addLineClass(lineNumber, 'text', 'columnSplit');
} }
// definition lists // definition lists
@@ -231,14 +219,14 @@ const Editor = createReactClass({
const regex = /^([^\n]*?:?\s?)(::[^\n]*)(?:\n|$)/ymd; // the `d` flag, for match indices, throws an ESLint error. const regex = /^([^\n]*?:?\s?)(::[^\n]*)(?:\n|$)/ymd; // the `d` flag, for match indices, throws an ESLint error.
let match; let match;
while ((match = regex.exec(line)) != null){ while ((match = regex.exec(line)) != null){
codeMirror?.markText({ line: lineNumber, ch: match.indices[0][0] }, { line: lineNumber, ch: match.indices[0][1] }, { className: 'dl-highlight' }); codeMirror.markText({ line: lineNumber, ch: match.indices[0][0] }, { line: lineNumber, ch: match.indices[0][1] }, { className: 'dl-highlight' });
codeMirror?.markText({ line: lineNumber, ch: match.indices[1][0] }, { line: lineNumber, ch: match.indices[1][1] }, { className: 'dt-highlight' }); codeMirror.markText({ line: lineNumber, ch: match.indices[1][0] }, { line: lineNumber, ch: match.indices[1][1] }, { className: 'dt-highlight' });
codeMirror?.markText({ line: lineNumber, ch: match.indices[2][0] }, { line: lineNumber, ch: match.indices[2][1] }, { className: 'dd-highlight' }); codeMirror.markText({ line: lineNumber, ch: match.indices[2][0] }, { line: lineNumber, ch: match.indices[2][1] }, { className: 'dd-highlight' });
const ddIndex = match.indices[2][0]; const ddIndex = match.indices[2][0];
const colons = /::/g; const colons = /::/g;
const colonMatches = colons.exec(match[2]); const colonMatches = colons.exec(match[2]);
if(colonMatches !== null){ if(colonMatches !== null){
codeMirror?.markText({ line: lineNumber, ch: colonMatches.index + ddIndex }, { line: lineNumber, ch: colonMatches.index + colonMatches[0].length + ddIndex }, { className: 'dl-colon-highlight' }); codeMirror.markText({ line: lineNumber, ch: colonMatches.index + ddIndex }, { line: lineNumber, ch: colonMatches.index + colonMatches[0].length + ddIndex }, { className: 'dl-colon-highlight' });
} }
} }
} }
@@ -255,7 +243,7 @@ const Editor = createReactClass({
const match = subRegex.exec(line) || superRegex.exec(line); const match = subRegex.exec(line) || superRegex.exec(line);
if(match) { if(match) {
isSuper = !subRegex.lastIndex; isSuper = !subRegex.lastIndex;
codeMirror?.markText({ line: lineNumber, ch: match.index }, { line: lineNumber, ch: match.index + match[0].length }, { className: isSuper ? 'superscript' : 'subscript' }); codeMirror.markText({ line: lineNumber, ch: match.index }, { line: lineNumber, ch: match.index + match[0].length }, { className: isSuper ? 'superscript' : 'subscript' });
} }
startIndex = line.indexOf('^', Math.max(startIndex + 1, subRegex.lastIndex, superRegex.lastIndex)); startIndex = line.indexOf('^', Math.max(startIndex + 1, subRegex.lastIndex, superRegex.lastIndex));
} }
@@ -266,7 +254,7 @@ const Editor = createReactClass({
const regex = /(?:^|[^{\n])({(?=((?:[:=](?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':={}\s]*)*))\2})/gm; const regex = /(?:^|[^{\n])({(?=((?:[:=](?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':={}\s]*)*))\2})/gm;
let match; let match;
while ((match = regex.exec(line)) != null) { while ((match = regex.exec(line)) != null) {
codeMirror?.markText({ line: lineNumber, ch: line.indexOf(match[1]) }, { line: lineNumber, ch: line.indexOf(match[1]) + match[1].length }, { className: 'injection' }); codeMirror.markText({ line: lineNumber, ch: line.indexOf(match[1]) }, { line: lineNumber, ch: line.indexOf(match[1]) + match[1].length }, { className: 'injection' });
} }
} }
// Highlight inline spans {{content}} // Highlight inline spans {{content}}
@@ -284,7 +272,7 @@ const Editor = createReactClass({
blockCount = 0; blockCount = 0;
continue; continue;
} }
codeMirror?.markText({ line: lineNumber, ch: match.index }, { line: lineNumber, ch: match.index + match[0].length }, { className: 'inline-block' }); codeMirror.markText({ line: lineNumber, ch: match.index }, { line: lineNumber, ch: match.index + match[0].length }, { className: 'inline-block' });
} }
} else if(line.trimLeft().startsWith('{{') || line.trimLeft().startsWith('}}')){ } else if(line.trimLeft().startsWith('{{') || line.trimLeft().startsWith('}}')){
// Highlight block divs {{\n Content \n}} // Highlight block divs {{\n Content \n}}
@@ -293,7 +281,7 @@ const Editor = createReactClass({
const match = line.match(/^ *{{(?=((?:[:=](?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':={}\s]*)*))\1 *$|^ *}}$/); const match = line.match(/^ *{{(?=((?:[:=](?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':={}\s]*)*))\1 *$|^ *}}$/);
if(match) if(match)
endCh = match.index+match[0].length; endCh = match.index+match[0].length;
codeMirror?.markText({ line: lineNumber, ch: 0 }, { line: lineNumber, ch: endCh }, { className: 'block' }); codeMirror.markText({ line: lineNumber, ch: 0 }, { line: lineNumber, ch: endCh }, { className: 'block' });
} }
// Emojis // Emojis
@@ -314,11 +302,11 @@ const Editor = createReactClass({
const endPos = { line: lineNumber, ch: match.index + match[0].length }; const endPos = { line: lineNumber, ch: match.index + match[0].length };
// Iterate over conflicting marks and clear them // Iterate over conflicting marks and clear them
const marks = codeMirror?.findMarks(startPos, endPos); const marks = codeMirror.findMarks(startPos, endPos);
marks.forEach(function(marker) { marks.forEach(function(marker) {
if(!marker.__isFold) marker.clear(); if(!marker.__isFold) marker.clear();
}); });
codeMirror?.markText(startPos, endPos, { className: 'emoji' }); codeMirror.markText(startPos, endPos, { className: 'emoji' });
} }
startIndex = line.indexOf(':', Math.max(startIndex + 1, emojiRegex.lastIndex)); startIndex = line.indexOf(':', Math.max(startIndex + 1, emojiRegex.lastIndex));
} }
@@ -378,51 +366,53 @@ const Editor = createReactClass({
const textString = this.props.brew.text.split(textSplit).slice(0, targetPage-1).join(textSplit); const textString = this.props.brew.text.split(textSplit).slice(0, targetPage-1).join(textSplit);
const targetLine = textString.match('\n') ? textString.split('\n').length - 1 : -1; const targetLine = textString.match('\n') ? textString.split('\n').length - 1 : -1;
let currentY = this.codeEditor.current.codeMirror?.getScrollInfo().top; let currentY = this.codeEditor.current.codeMirror.getScrollInfo().top;
let targetY = this.codeEditor.current.codeMirror?.heightAtLine(targetLine, 'local', true); let targetY = this.codeEditor.current.codeMirror.heightAtLine(targetLine, 'local', true);
let scrollingTimeout; let scrollingTimeout;
const checkIfScrollComplete = ()=>{ // Prevent interrupting a scroll in progress if user clicks multiple times const checkIfScrollComplete = ()=>{ // Prevent interrupting a scroll in progress if user clicks multiple times
clearTimeout(scrollingTimeout); // Reset the timer every time a scroll event occurs clearTimeout(scrollingTimeout); // Reset the timer every time a scroll event occurs
scrollingTimeout = setTimeout(()=>{ scrollingTimeout = setTimeout(()=>{
isJumping = false; isJumping = false;
this.codeEditor.current.codeMirror?.off('scroll', checkIfScrollComplete); this.codeEditor.current.codeMirror.off('scroll', checkIfScrollComplete);
}, 150); // If 150 ms pass without a scroll event, assume scrolling is done }, 150); // If 150 ms pass without a scroll event, assume scrolling is done
}; };
isJumping = true; isJumping = true;
checkIfScrollComplete(); checkIfScrollComplete();
if (this.codeEditor.current?.codeMirror) { this.codeEditor.current.codeMirror.on('scroll', checkIfScrollComplete);
this.codeEditor.current.codeMirror?.on('scroll', checkIfScrollComplete);
}
if(smooth) { if(smooth) {
//Scroll 1/10 of the way every 10ms until 1px off. //Scroll 1/10 of the way every 10ms until 1px off.
const incrementalScroll = setInterval(()=>{ const incrementalScroll = setInterval(()=>{
currentY += (targetY - currentY) / 10; currentY += (targetY - currentY) / 10;
this.codeEditor.current.codeMirror?.scrollTo(null, currentY); this.codeEditor.current.codeMirror.scrollTo(null, currentY);
// Update target: target height is not accurate until within +-10 lines of the visible window // Update target: target height is not accurate until within +-10 lines of the visible window
if(Math.abs(targetY - currentY > 100)) if(Math.abs(targetY - currentY > 100))
targetY = this.codeEditor.current.codeMirror?.heightAtLine(targetLine, 'local', true); targetY = this.codeEditor.current.codeMirror.heightAtLine(targetLine, 'local', true);
// End when close enough // End when close enough
if(Math.abs(targetY - currentY) < 1) { if(Math.abs(targetY - currentY) < 1) {
this.codeEditor.current.codeMirror?.scrollTo(null, targetY); // Scroll any remaining difference this.codeEditor.current.codeMirror.scrollTo(null, targetY); // Scroll any remaining difference
this.codeEditor.current.setCursorPosition({ line: targetLine + 1, ch: 0 }); this.codeEditor.current.setCursorPosition({ line: targetLine + 1, ch: 0 });
this.codeEditor.current.codeMirror?.addLineClass(targetLine + 1, 'wrap', 'sourceMoveFlash'); this.codeEditor.current.codeMirror.addLineClass(targetLine + 1, 'wrap', 'sourceMoveFlash');
clearInterval(incrementalScroll); clearInterval(incrementalScroll);
} }
}, 10); }, 10);
} else { } else {
this.codeEditor.current.codeMirror?.scrollTo(null, targetY); // Scroll any remaining difference this.codeEditor.current.codeMirror.scrollTo(null, targetY); // Scroll any remaining difference
this.codeEditor.current.setCursorPosition({ line: targetLine + 1, ch: 0 }); this.codeEditor.current.setCursorPosition({ line: targetLine + 1, ch: 0 });
this.codeEditor.current.codeMirror?.addLineClass(targetLine + 1, 'wrap', 'sourceMoveFlash'); this.codeEditor.current.codeMirror.addLineClass(targetLine + 1, 'wrap', 'sourceMoveFlash');
} }
}, },
//Called when there are changes to the editor's dimensions //Called when there are changes to the editor's dimensions
update : function(){}, update : function(){
const snipHeight = document.querySelector('.editor > .snippetBar').offsetHeight;
if(snipHeight !== this.state.snippetbarHeight)
this.setState({ snippetbarHeight: snipHeight });
},
updateEditorTheme : function(newTheme){ updateEditorTheme : function(newTheme){
window.localStorage.setItem(EDITOR_THEME_KEY, newTheme); window.localStorage.setItem(EDITOR_THEME_KEY, newTheme);
@@ -447,7 +437,7 @@ const Editor = createReactClass({
onChange={this.props.onBrewChange('text')} onChange={this.props.onBrewChange('text')}
editorTheme={this.state.editorTheme} editorTheme={this.state.editorTheme}
rerenderParent={this.rerenderParent} rerenderParent={this.rerenderParent}
style={{ height: `calc(100% - ${this.state.snippetBarHeight}px)` }} /> style={{ height: `calc(100% - ${this.state.snippetbarHeight}px)` }} />
</>; </>;
} }
if(this.isStyle()){ if(this.isStyle()){
@@ -461,7 +451,7 @@ const Editor = createReactClass({
enableFolding={true} enableFolding={true}
editorTheme={this.state.editorTheme} editorTheme={this.state.editorTheme}
rerenderParent={this.rerenderParent} rerenderParent={this.rerenderParent}
style={{ height: `calc(100% - ${this.state.snippetBarHeight}px)` }} /> style={{ height: `calc(100% - ${this.state.snippetbarHeight}px)` }} />
</>; </>;
} }
if(this.isMeta()){ if(this.isMeta()){
@@ -478,6 +468,7 @@ const Editor = createReactClass({
userThemes={this.props.userThemes}/> userThemes={this.props.userThemes}/>
</>; </>;
} }
if(this.isSnip()){ if(this.isSnip()){
if(!this.props.brew.snippets) { this.props.brew.snippets = DEFAULT_SNIPPET_TEXT; } if(!this.props.brew.snippets) { this.props.brew.snippets = DEFAULT_SNIPPET_TEXT; }
return <> return <>
@@ -490,7 +481,7 @@ const Editor = createReactClass({
enableFolding={true} enableFolding={true}
editorTheme={this.state.editorTheme} editorTheme={this.state.editorTheme}
rerenderParent={this.rerenderParent} rerenderParent={this.rerenderParent}
style={{ height: `calc(100% -${this.state.snippetBarHeight}px)` }} /> style={{ height: `calc(100% - ${this.state.snippetbarHeight}px)` }} />
</>; </>;
} }
}, },
@@ -544,4 +535,4 @@ const Editor = createReactClass({
} }
}); });
export default Editor; module.exports = Editor;

View File

@@ -1,18 +1,19 @@
/* eslint-disable max-lines */ /* eslint-disable max-lines */
import './metadataEditor.less'; require('./metadataEditor.less');
import React from 'react'; const React = require('react');
import createReactClass from 'create-react-class'; const createClass = require('create-react-class');
import _ from 'lodash'; const _ = require('lodash');
import request from '../../utils/request-middleware.js'; import request from '../../utils/request-middleware.js';
import Combobox from '../../../components/combobox.jsx'; const Combobox = require('client/components/combobox.jsx');
import TagInput from '../tagInput/tagInput.jsx'; const TagInput = require('../tagInput/tagInput.jsx');
import Themes from 'themes/themes.json';
import validations from './validations.js'; const Themes = require('themes/themes.json');
const validations = require('./validations.js');
const SYSTEMS = ['5e', '4e', '3.5e', 'Pathfinder']; const SYSTEMS = ['5e', '4e', '3.5e', 'Pathfinder'];
import homebreweryThumbnail from '../../thumbnail.png'; const homebreweryThumbnail = require('../../thumbnail.png');
const callIfExists = (val, fn, ...args)=>{ const callIfExists = (val, fn, ...args)=>{
if(val[fn]) { if(val[fn]) {
@@ -20,7 +21,7 @@ const callIfExists = (val, fn, ...args)=>{
} }
}; };
const MetadataEditor = createReactClass({ const MetadataEditor = createClass({
displayName : 'MetadataEditor', displayName : 'MetadataEditor',
getDefaultProps : function() { getDefaultProps : function() {
return { return {
@@ -410,4 +411,4 @@ const MetadataEditor = createReactClass({
} }
}); });
export default MetadataEditor; module.exports = MetadataEditor;

View File

@@ -1,4 +1,4 @@
export default { module.exports = {
title : [ title : [
(value)=>{ (value)=>{
return value?.length > 100 ? 'Max title length of 100 characters' : null; return value?.length > 100 ? 'Max title length of 100 characters' : null;

View File

@@ -1,36 +1,29 @@
/*eslint max-lines: ["warn", {"max": 350, "skipBlankLines": true, "skipComments": true}]*/ /*eslint max-lines: ["warn", {"max": 350, "skipBlankLines": true, "skipComments": true}]*/
import './snippetbar.less'; require('./snippetbar.less');
import React from 'react'; const React = require('react');
import createReactClass from 'create-react-class'; const createClass = require('create-react-class');
const _ = require('lodash');
import _ from 'lodash'; const cx = require('classnames');
import cx from 'classnames';
import { loadHistory } from '../../utils/versionHistory.js'; import { loadHistory } from '../../utils/versionHistory.js';
import { brewSnippetsToJSON } from '../../../../shared/helpers.js'; import { brewSnippetsToJSON } from '../../../../shared/helpers.js';
import Legacy5ePHB from 'themes/Legacy/5ePHB/snippets.js'; //Import all themes
import V3_5ePHB from 'themes/V3/5ePHB/snippets.js'; const ThemeSnippets = {};
import V3_5eDMG from 'themes/V3/5eDMG/snippets.js'; ThemeSnippets['Legacy_5ePHB'] = require('themes/Legacy/5ePHB/snippets.js');
import V3_Journal from 'themes/V3/Journal/snippets.js'; ThemeSnippets['V3_5ePHB'] = require('themes/V3/5ePHB/snippets.js');
import V3_Blank from 'themes/V3/Blank/snippets.js'; ThemeSnippets['V3_5eDMG'] = require('themes/V3/5eDMG/snippets.js');
ThemeSnippets['V3_Journal'] = require('themes/V3/Journal/snippets.js');
ThemeSnippets['V3_Blank'] = require('themes/V3/Blank/snippets.js');
const ThemeSnippets = { const EditorThemes = require('build/homebrew/codeMirror/editorThemes.json');
Legacy_5ePHB : Legacy5ePHB,
V3_5ePHB : V3_5ePHB,
V3_5eDMG : V3_5eDMG,
V3_Journal : V3_Journal,
V3_Blank : V3_Blank,
};
import EditorThemes from 'build/homebrew/codeMirror/editorThemes.json';
const execute = function(val, props){ const execute = function(val, props){
if(_.isFunction(val)) return val(props); if(_.isFunction(val)) return val(props);
return val; return val;
}; };
const Snippetbar = createReactClass({ const Snippetbar = createClass({
displayName : 'SnippetBar', displayName : 'SnippetBar',
getDefaultProps : function() { getDefaultProps : function() {
return { return {
@@ -288,9 +281,9 @@ const Snippetbar = createReactClass({
} }
}); });
export default Snippetbar; module.exports = Snippetbar;
const SnippetGroup = createReactClass({ const SnippetGroup = createClass({
displayName : 'SnippetGroup', displayName : 'SnippetGroup',
getDefaultProps : function() { getDefaultProps : function() {
return { return {

View File

@@ -14,7 +14,7 @@
.snippets { .snippets {
display : flex; display : flex;
justify-content : flex-start; justify-content : flex-start;
min-width : 499.35px; //must be controlled every time an item is added, must be hardcoded for the wrapping as it is applied min-width : 432.18px; //must be controlled every time an item is added, must be hardcoded for the wrapping as it is applied
} }
.editors { .editors {
@@ -237,7 +237,7 @@
} }
} }
@container editor (width < 750px) { @container editor (width < 683px) {
.snippetBar { .snippetBar {
.editors { .editors {
flex : 1; flex : 1;

View File

@@ -1,6 +1,7 @@
import './tagInput.less'; require('./tagInput.less');
import React, { useState, useEffect } from 'react'; const React = require('react');
import _ from 'lodash'; const { useState, useEffect } = React;
const _ = require('lodash');
const TagInput = ({ unique = true, values = [], ...props })=>{ const TagInput = ({ unique = true, values = [], ...props })=>{
const [tempInputText, setTempInputText] = useState(''); const [tempInputText, setTempInputText] = useState('');
@@ -101,4 +102,4 @@ const TagInput = ({ unique = true, values = [], ...props })=>{
); );
}; };
export default TagInput; module.exports = TagInput;

View File

@@ -1,4 +1,4 @@
/* eslint-disable camelcase */
import 'core-js/es/string/to-well-formed.js'; //Polyfill for older browsers import 'core-js/es/string/to-well-formed.js'; //Polyfill for older browsers
import './homebrew.less'; import './homebrew.less';
import React from 'react'; import React from 'react';

View File

@@ -1,9 +1,9 @@
import React from 'react'; const React = require('react');
import createReactClass from 'create-react-class'; const createClass = require('create-react-class');
import request from 'superagent'; const Nav = require('naturalcrit/nav/nav.jsx');
import Nav from './nav.jsx'; const request = require('superagent');
const Account = createReactClass({ const Account = createClass({
displayName : 'AccountNavItem', displayName : 'AccountNavItem',
getInitialState : function() { getInitialState : function() {
return { return {
@@ -70,7 +70,7 @@ const Account = createReactClass({
{global.account.username} {global.account.username}
</Nav.item> </Nav.item>
<Nav.item <Nav.item
href={`/user/${encodeURIComponent(global.account.username)}`} href={`/user/${encodeURI(global.account.username)}`}
color='yellow' color='yellow'
icon='fas fa-beer' icon='fas fa-beer'
> >
@@ -111,4 +111,4 @@ const Account = createReactClass({
} }
}); });
export default Account; module.exports = Account;

View File

@@ -1,6 +1,6 @@
import './error-navitem.less'; require('./error-navitem.less');
import React from 'react'; const React = require('react');
import Nav from './nav.jsx'; const Nav = require('naturalcrit/nav/nav.jsx');
const ErrorNavItem = ({ error = '', clearError })=>{ const ErrorNavItem = ({ error = '', clearError })=>{
const response = error.response; const response = error.response;
@@ -144,4 +144,4 @@ const ErrorNavItem = ({ error = '', clearError })=>{
</Nav.item>; </Nav.item>;
}; };
export default ErrorNavItem; module.exports = ErrorNavItem;

View File

@@ -1,9 +1,9 @@
import React from 'react'; const React = require('react');
import dedent from 'dedent'; const dedent = require('dedent-tabs').default;
import Nav from './nav.jsx'; const Nav = require('naturalcrit/nav/nav.jsx');
export default function(props){ module.exports = function(props){
return <Nav.dropdown> return <Nav.dropdown>
<Nav.item color='grey' icon='fas fa-question-circle'> <Nav.item color='grey' icon='fas fa-question-circle'>
need help? need help?

View File

@@ -1,11 +1,11 @@
import React from 'react'; const React = require('react');
import createReactClass from 'create-react-class'; const createClass = require('create-react-class');
import Moment from 'moment'; const Moment = require('moment');
import Nav from './nav.jsx'; const Nav = require('naturalcrit/nav/nav.jsx');
const MetadataNav = createReactClass({ const MetadataNav = createClass({
displayName : 'MetadataNav', displayName : 'MetadataNav',
getDefaultProps : function() { getDefaultProps : function() {
return { return {
@@ -32,7 +32,7 @@ const MetadataNav = createReactClass({
return <> return <>
{this.props.brew.authors.map((author, idx, arr)=>{ {this.props.brew.authors.map((author, idx, arr)=>{
const spacer = arr.length - 1 == idx ? <></> : <span>, </span>; const spacer = arr.length - 1 == idx ? <></> : <span>, </span>;
return <span key={idx}><a className='userPageLink' href={`/user/${encodeURIComponent(author)}`}>{author}</a>{spacer}</span>; return <span key={idx}><a className='userPageLink' href={`/user/${author}`}>{author}</a>{spacer}</span>;
})} })}
</>; </>;
}, },
@@ -86,4 +86,4 @@ const MetadataNav = createReactClass({
}); });
export default MetadataNav; module.exports = MetadataNav;

View File

@@ -1,11 +1,11 @@
import './navbar.less'; require('./navbar.less');
import React from 'react'; const React = require('react');
import createReactClass from 'create-react-class'; const createClass = require('create-react-class');
import Nav from './nav.jsx'; const Nav = require('naturalcrit/nav/nav.jsx');
import PatreonNavItem from './patreon.navitem.jsx'; const PatreonNavItem = require('./patreon.navitem.jsx');
const Navbar = createReactClass({ const Navbar = createClass({
displayName : 'Navbar', displayName : 'Navbar',
getInitialState : function() { getInitialState : function() {
return { return {
@@ -49,4 +49,4 @@ const Navbar = createReactClass({
} }
}); });
export default Navbar; module.exports = Navbar;

View File

@@ -1,18 +1,21 @@
import React from 'react'; const React = require('react');
import _ from 'lodash'; const _ = require('lodash');
import Nav from './nav.jsx'; const Nav = require('naturalcrit/nav/nav.jsx');
import { splitTextStyleAndMetadata } from '../../../shared/helpers.js'; const { splitTextStyleAndMetadata } = require('../../../shared/helpers.js'); // Importing the function from helpers.js
const BREWKEY = 'HB_newPage_content'; const BREWKEY = 'homebrewery-new';
const STYLEKEY = 'HB_newPage_style'; const STYLEKEY = 'homebrewery-new-style';
const METAKEY = 'HB_newPage_meta'; const METAKEY = 'homebrewery-new-meta';
const NewBrew = ()=>{ const NewBrew = ()=>{
const handleFileChange = (e)=>{ const handleFileChange = (e)=>{
const file = e.target.files[0]; const file = e.target.files[0];
if(!file) return; if(!file) return;
if(!confirmLocalStorageChange()) return; const currentNew = localStorage.getItem(BREWKEY);
if(currentNew && !confirm(
`You have some text in the new brew space, if you load a file that text will be lost, are you sure you want to load the file?`
)) return;
const reader = new FileReader(); const reader = new FileReader();
reader.onload = (e)=>{ reader.onload = (e)=>{
@@ -34,35 +37,12 @@ const NewBrew = ()=>{
alert(`This file is invalid: ${!type ? 'Missing file extension' :`.${type} files are not supported`}. Only .txt files exported from the Homebrewery are allowed.`); alert(`This file is invalid: ${!type ? 'Missing file extension' :`.${type} files are not supported`}. Only .txt files exported from the Homebrewery are allowed.`);
console.log(file); console.log(file);
}; };
reader.readAsText(file); reader.readAsText(file);
}; };
const confirmLocalStorageChange = ()=>{
const currentText = localStorage.getItem(BREWKEY);
const currentStyle = localStorage.getItem(STYLEKEY);
const currentMeta = localStorage.getItem(METAKEY);
// TRUE if no data in any local storage key
// TRUE if data in any local storage key AND approval given
// FALSE if data in any local storage key AND approval declined
return (!(currentText || currentStyle || currentMeta) || confirm(
`You have made changes in the new brew space. If you continue, that information will be PERMANENTLY LOST.\nAre you sure you wish to continue?`
));
};
const clearLocalStorage = ()=>{
if(!confirmLocalStorageChange()) return;
localStorage.removeItem(BREWKEY);
localStorage.removeItem(STYLEKEY);
localStorage.removeItem(METAKEY);
window.location.href = '/new';
return;
};
return ( return (
<Nav.dropdown> <Nav.dropdown>
@@ -70,34 +50,27 @@ const NewBrew = ()=>{
className='new' className='new'
color='purple' color='purple'
icon='fa-solid fa-plus-square'> icon='fa-solid fa-plus-square'>
new new
</Nav.item> </Nav.item>
<Nav.item <Nav.item
className='new' className='fromBlank'
href='/new' href='/new'
newTab={true} newTab={true}
color='purple' color='purple'
icon='fa-solid fa-file'> icon='fa-solid fa-file'>
resume draft from blank
</Nav.item>
<Nav.item
className='fromBlank'
newTab={true}
color='yellow'
icon='fa-solid fa-file-circle-plus'
onClick={()=>{ clearLocalStorage(); }}>
from blank
</Nav.item> </Nav.item>
<Nav.item <Nav.item
className='fromFile' className='fromFile'
color='green' color='purple'
icon='fa-solid fa-upload' icon='fa-solid fa-upload'
onClick={()=>{ document.getElementById('uploadTxt').click(); }}> onClick={()=>{ document.getElementById('uploadTxt').click(); }}>
<input id='uploadTxt' className='newFromLocal' type='file' onChange={handleFileChange} style={{ display: 'none' }} /> <input id='uploadTxt' className='newFromLocal' type='file' onChange={handleFileChange} style={{ display: 'none' }} />
from file from file
</Nav.item> </Nav.item>
</Nav.dropdown> </Nav.dropdown>
); );
}; };
export default NewBrew; module.exports = NewBrew;

View File

@@ -1,7 +1,7 @@
import React from 'react'; const React = require('react');
import Nav from './nav.jsx'; const Nav = require('naturalcrit/nav/nav.jsx');
export default function(props){ module.exports = function(props){
return <Nav.item return <Nav.item
className='patreon' className='patreon'
newTab={true} newTab={true}

View File

@@ -1,8 +1,8 @@
import React from 'react'; const React = require('react');
import Nav from './nav.jsx'; const Nav = require('naturalcrit/nav/nav.jsx');
import { printCurrentBrew } from '../../../shared/helpers.js'; const { printCurrentBrew } = require('../../../shared/helpers.js');
export default function(){ module.exports = function(){
return <Nav.item onClick={printCurrentBrew} color='purple' icon='far fa-file-pdf'> return <Nav.item onClick={printCurrentBrew} color='purple' icon='far fa-file-pdf'>
get PDF get PDF
</Nav.item>; </Nav.item>;

View File

@@ -1,15 +1,15 @@
import React from 'react'; const React = require('react');
import createReactClass from 'create-react-class'; const createClass = require('create-react-class');
import _ from 'lodash'; const _ = require('lodash');
import Moment from 'moment'; const Moment = require('moment');
import Nav from './nav.jsx'; const Nav = require('naturalcrit/nav/nav.jsx');
const EDIT_KEY = 'HB_nav_recentlyEdited'; const EDIT_KEY = 'HB_nav_recentlyEdited';
const VIEW_KEY = 'HB_nav_recentlyViewed'; const VIEW_KEY = 'HB_nav_recentlyViewed';
const RecentItems = createReactClass({ const RecentItems = createClass({
DisplayName : 'RecentItems', DisplayName : 'RecentItems',
getDefaultProps : function() { getDefaultProps : function() {
return { return {
@@ -175,7 +175,7 @@ const RecentItems = createReactClass({
}); });
export default { module.exports = {
edited : (props)=>{ edited : (props)=>{
return <RecentItems return <RecentItems

View File

@@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import dedent from 'dedent'; import dedent from 'dedent-tabs';
import Nav from './nav.jsx'; import Nav from 'naturalcrit/nav/nav.jsx';
const getShareId = (brew)=>( const getShareId = (brew)=>(
brew.googleId && !brew.stubbed brew.googleId && !brew.stubbed

View File

@@ -1,8 +1,8 @@
import React from 'react'; const React = require('react');
import Nav from './nav.jsx'; const Nav = require('naturalcrit/nav/nav.jsx');
export default function (props) { module.exports = function (props) {
return ( return (
<Nav.item <Nav.item
color='purple' color='purple'

View File

@@ -1,7 +1,7 @@
import React from 'react'; const React = require('react');
import moment from 'moment'; const moment = require('moment');
import UIPage from '../basePages/uiPage/uiPage.jsx'; const UIPage = require('../basePages/uiPage/uiPage.jsx');
import NaturalCritIcon from '../../../components/svg/naturalcrit-d20.svg.jsx'; const NaturalCritIcon = require('client/components/svg/naturalcrit-d20.svg.jsx');
let SAVEKEY = ''; let SAVEKEY = '';
@@ -79,4 +79,4 @@ const AccountPage = (props)=>{
</UIPage>); </UIPage>);
}; };
export default AccountPage; module.exports = AccountPage;

View File

@@ -1,11 +1,12 @@
import './brewItem.less'; require('./brewItem.less');
import React, { useCallback } from 'react'; const React = require('react');
import moment from 'moment'; const { useCallback } = React;
const moment = require('moment');
import request from '../../../../utils/request-middleware.js'; import request from '../../../../utils/request-middleware.js';
import googleDriveIcon from '../../../../googleDrive.svg'; const googleDriveIcon = require('../../../../googleDrive.svg');
import homebreweryIcon from '../../../../thumbnail.svg'; const homebreweryIcon = require('../../../../thumbnail.svg');
import dedent from 'dedent'; const dedent = require('dedent-tabs').default;
const BrewItem = ({ const BrewItem = ({
brew = { brew = {
@@ -142,7 +143,7 @@ const BrewItem = ({
<span title="Username contained an email address; hidden to protect user's privacy"> <span title="Username contained an email address; hidden to protect user's privacy">
{author} {author}
</span> </span>
) : (<a href={`/user/${encodeURIComponent(author)}`}>{author}</a>)} ) : (<a href={`/user/${author}`}>{author}</a>)}
{index < brew.authors.length - 1 && ', '} {index < brew.authors.length - 1 && ', '}
</React.Fragment> </React.Fragment>
))} ))}
@@ -175,4 +176,4 @@ const BrewItem = ({
); );
}; };
export default BrewItem; module.exports = BrewItem;

View File

@@ -1,11 +1,11 @@
/*eslint max-lines: ["warn", {"max": 300, "skipBlankLines": true, "skipComments": true}]*/ /*eslint max-lines: ["warn", {"max": 300, "skipBlankLines": true, "skipComments": true}]*/
import './listPage.less'; require('./listPage.less');
import React from 'react'; const React = require('react');
import createReactClass from 'create-react-class'; const createClass = require('create-react-class');
import _ from 'lodash'; const _ = require('lodash');
import moment from 'moment'; const moment = require('moment');
import BrewItem from './brewItem/brewItem.jsx'; const BrewItem = require('./brewItem/brewItem.jsx');
const USERPAGE_SORT_DIR = 'HB_listPage_sortDir'; const USERPAGE_SORT_DIR = 'HB_listPage_sortDir';
const USERPAGE_SORT_TYPE = 'HB_listPage_sortType'; const USERPAGE_SORT_TYPE = 'HB_listPage_sortType';
@@ -14,7 +14,7 @@ const USERPAGE_GROUP_VISIBILITY_PREFIX = 'HB_listPage_visibility_group';
const DEFAULT_SORT_TYPE = 'alpha'; const DEFAULT_SORT_TYPE = 'alpha';
const DEFAULT_SORT_DIR = 'asc'; const DEFAULT_SORT_DIR = 'asc';
const ListPage = createReactClass({ const ListPage = createClass({
displayName : 'ListPage', displayName : 'ListPage',
getDefaultProps : function() { getDefaultProps : function() {
return { return {
@@ -279,4 +279,4 @@ const ListPage = createReactClass({
} }
}); });
export default ListPage; module.exports = ListPage;

View File

@@ -1,17 +1,16 @@
import './uiPage.less'; require('./uiPage.less');
import React from 'react'; const React = require('react');
import createReactClass from 'create-react-class'; const createClass = require('create-react-class');
import Nav from '../../../navbar/nav.jsx'; const Nav = require('naturalcrit/nav/nav.jsx');
import Navbar from '../../../navbar/navbar.jsx'; const Navbar = require('../../../navbar/navbar.jsx');
import NewBrewItem from '../../../navbar/newbrew.navitem.jsx'; const NewBrewItem = require('../../../navbar/newbrew.navitem.jsx');
import HelpNavItem from '../../../navbar/help.navitem.jsx'; const HelpNavItem = require('../../../navbar/help.navitem.jsx');
import RecentNavItems from '../../../navbar/recent.navitem.jsx'; const RecentNavItem = require('../../../navbar/recent.navitem.jsx').both;
const { both: RecentNavItem } = RecentNavItems; const Account = require('../../../navbar/account.navitem.jsx');
import Account from '../../../navbar/account.navitem.jsx';
const UIPage = createReactClass({ const UIPage = createClass({
displayName : 'UIPage', displayName : 'UIPage',
render : function(){ render : function(){
@@ -36,4 +35,4 @@ const UIPage = createReactClass({
} }
}); });
export default UIPage; module.exports = UIPage;

View File

@@ -4,17 +4,17 @@ import './editPage.less';
// Common imports // Common imports
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import request from '../../utils/request-middleware.js'; import request from '../../utils/request-middleware.js';
import Markdown from '../../../../shared/markdown.js'; import Markdown from 'markdown.js';
import _ from 'lodash'; import _ from 'lodash';
import { DEFAULT_BREW_LOAD } from '../../../../server/brewDefaults.js'; import { DEFAULT_BREW_LOAD } from '../../../../server/brewDefaults.js';
import { printCurrentBrew, fetchThemeBundle, splitTextStyleAndMetadata } from '../../../../shared/helpers.js'; import { printCurrentBrew, fetchThemeBundle, splitTextStyleAndMetadata } from '../../../../shared/helpers.js';
import SplitPane from '../../../components/splitPane/splitPane.jsx'; import SplitPane from 'client/components/splitPane/splitPane.jsx';
import Editor from '../../editor/editor.jsx'; import Editor from '../../editor/editor.jsx';
import BrewRenderer from '../../brewRenderer/brewRenderer.jsx'; import BrewRenderer from '../../brewRenderer/brewRenderer.jsx';
import Nav from '../../navbar/nav.jsx'; import Nav from 'naturalcrit/nav/nav.jsx';
import Navbar from '../../navbar/navbar.jsx'; import Navbar from '../../navbar/navbar.jsx';
import NewBrewItem from '../../navbar/newbrew.navitem.jsx'; import NewBrewItem from '../../navbar/newbrew.navitem.jsx';
import AccountNavItem from '../../navbar/account.navitem.jsx'; import AccountNavItem from '../../navbar/account.navitem.jsx';
@@ -22,8 +22,7 @@ import ErrorNavItem from '../../navbar/error-navitem.jsx';
import HelpNavItem from '../../navbar/help.navitem.jsx'; import HelpNavItem from '../../navbar/help.navitem.jsx';
import VaultNavItem from '../../navbar/vault.navitem.jsx'; import VaultNavItem from '../../navbar/vault.navitem.jsx';
import PrintNavItem from '../../navbar/print.navitem.jsx'; import PrintNavItem from '../../navbar/print.navitem.jsx';
import RecentNavItems from '../../navbar/recent.navitem.jsx'; import { both as RecentNavItem } from '../../navbar/recent.navitem.jsx';
const { both: RecentNavItem } = RecentNavItems;
// Page specific imports // Page specific imports
import { Meta } from 'vitreum/headtags'; import { Meta } from 'vitreum/headtags';
@@ -120,10 +119,6 @@ const EditPage = (props)=>{
if(autoSaveEnabled) trySave(false, hasChange); if(autoSaveEnabled) trySave(false, hasChange);
}, [currentBrew]); }, [currentBrew]);
useEffect(()=>{
trySave(true);
}, [saveGoogle]);
const handleSplitMove = ()=>{ const handleSplitMove = ()=>{
editorRef.current?.update(); editorRef.current?.update();
}; };
@@ -184,6 +179,7 @@ const EditPage = (props)=>{
const toggleGoogleStorage = ()=>{ const toggleGoogleStorage = ()=>{
setSaveGoogle((prev)=>!prev); setSaveGoogle((prev)=>!prev);
setError(null); setError(null);
trySave(true);
}; };
const trySave = (immediate = false, hasChanges = true)=>{ const trySave = (immediate = false, hasChanges = true)=>{
@@ -217,7 +213,7 @@ const EditPage = (props)=>{
text : brew.text.normalize('NFC'), text : brew.text.normalize('NFC'),
pageCount : ((brew.renderer === 'legacy' ? brew.text.match(/\\page/g) : brew.text.match(/^\\page$/gm)) || []).length + 1, pageCount : ((brew.renderer === 'legacy' ? brew.text.match(/\\page/g) : brew.text.match(/^\\page$/gm)) || []).length + 1,
patches : stringifyPatches(makePatches(encodeURI(lastSavedBrew.current.text.normalize('NFC')), encodeURI(brew.text.normalize('NFC')))), patches : stringifyPatches(makePatches(encodeURI(lastSavedBrew.current.text.normalize('NFC')), encodeURI(brew.text.normalize('NFC')))),
hash : await md5(lastSavedBrew.current.text.normalize('NFC')), hash : await md5(lastSavedBrew.current.text),
textBin : undefined, textBin : undefined,
version : lastSavedBrew.current.version version : lastSavedBrew.current.version
}; };
@@ -416,4 +412,4 @@ const EditPage = (props)=>{
); );
}; };
export default EditPage; module.exports = EditPage;

View File

@@ -40,4 +40,4 @@ function LockNotification(props) {
</Dialog>; </Dialog>;
}; };
export default LockNotification; module.exports = LockNotification;

View File

@@ -1,8 +1,8 @@
import './errorPage.less'; require('./errorPage.less');
import React from 'react'; const React = require('react');
import UIPage from '../basePages/uiPage/uiPage.jsx'; const UIPage = require('../basePages/uiPage/uiPage.jsx');
import Markdown from '../../../../shared/markdown.js'; import Markdown from '../../../../shared/markdown.js';
import ErrorIndex from './errors/errorIndex.js'; const ErrorIndex = require('./errors/errorIndex.js');
const ErrorPage = ({ brew })=>{ const ErrorPage = ({ brew })=>{
// Retrieving the error text based on the brew's error code from ErrorIndex // Retrieving the error text based on the brew's error code from ErrorIndex
@@ -22,4 +22,4 @@ const ErrorPage = ({ brew })=>{
); );
}; };
export default ErrorPage; module.exports = ErrorPage;

View File

@@ -1,4 +1,4 @@
import dedent from 'dedent'; const dedent = require('dedent-tabs').default;
const loginUrl = 'https://www.naturalcrit.com/login'; const loginUrl = 'https://www.naturalcrit.com/login';
@@ -96,7 +96,7 @@ const errorIndex = (props)=>{
**Brew Title:** ${escape(props.brew.brewTitle) || 'Unable to show title'} **Brew Title:** ${escape(props.brew.brewTitle) || 'Unable to show title'}
**Current Authors:** ${props.brew.authors?.map((author)=>{return `[${author}](/user/${encodeURIComponent(author)})`;}).join(', ') || 'Unable to list authors'} **Current Authors:** ${props.brew.authors?.map((author)=>{return `[${author}](/user/${author})`;}).join(', ') || 'Unable to list authors'}
[Click here to be redirected to the brew's share page.](/share/${props.brew.shareId})`, [Click here to be redirected to the brew's share page.](/share/${props.brew.shareId})`,
@@ -111,7 +111,7 @@ const errorIndex = (props)=>{
**Brew Title:** ${escape(props.brew.brewTitle) || 'Unable to show title'} **Brew Title:** ${escape(props.brew.brewTitle) || 'Unable to show title'}
**Current Authors:** ${props.brew.authors?.map((author)=>{return `[${author}](/user/${encodeURIComponent(author)})`;}).join(', ') || 'Unable to list authors'} **Current Authors:** ${props.brew.authors?.map((author)=>{return `[${author}](/user/${author})`;}).join(', ') || 'Unable to list authors'}
[Click here to be redirected to the brew's share page.](/share/${props.brew.shareId})`, [Click here to be redirected to the brew's share page.](/share/${props.brew.shareId})`,
@@ -222,7 +222,7 @@ const errorIndex = (props)=>{
**Brew Title:** ${escape(props.brew.brewTitle)} **Brew Title:** ${escape(props.brew.brewTitle)}
**Brew Authors:** ${props.brew.authors?.map((author)=>{return `[${author}](/user/${encodeURIComponent(author)})`;}).join(', ') || 'Unable to list authors'}`, **Brew Authors:** ${props.brew.authors?.map((author)=>{return `[${author}](/user/${author})`;}).join(', ') || 'Unable to list authors'}`,
// ####### Admin page error ####### // ####### Admin page error #######
'52' : dedent` '52' : dedent`
@@ -268,4 +268,4 @@ const errorIndex = (props)=>{
}; };
}; };
export default errorIndex; module.exports = errorIndex;

View File

@@ -4,17 +4,17 @@ import './homePage.less';
// Common imports // Common imports
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import request from '../../utils/request-middleware.js'; import request from '../../utils/request-middleware.js';
import Markdown from '../../../../shared/markdown.js'; import Markdown from 'markdown.js';
import _ from 'lodash'; 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 SplitPane from '../../../components/splitPane/splitPane.jsx'; import SplitPane from 'client/components/splitPane/splitPane.jsx';
import Editor from '../../editor/editor.jsx'; import Editor from '../../editor/editor.jsx';
import BrewRenderer from '../../brewRenderer/brewRenderer.jsx'; import BrewRenderer from '../../brewRenderer/brewRenderer.jsx';
import Nav from '../../navbar/nav.jsx'; import Nav from 'naturalcrit/nav/nav.jsx';
import Navbar from '../../navbar/navbar.jsx'; import Navbar from '../../navbar/navbar.jsx';
import NewBrewItem from '../../navbar/newbrew.navitem.jsx'; import NewBrewItem from '../../navbar/newbrew.navitem.jsx';
import AccountNavItem from '../../navbar/account.navitem.jsx'; import AccountNavItem from '../../navbar/account.navitem.jsx';
@@ -22,9 +22,7 @@ import ErrorNavItem from '../../navbar/error-navitem.jsx';
import HelpNavItem from '../../navbar/help.navitem.jsx'; import HelpNavItem from '../../navbar/help.navitem.jsx';
import VaultNavItem from '../../navbar/vault.navitem.jsx'; import VaultNavItem from '../../navbar/vault.navitem.jsx';
import PrintNavItem from '../../navbar/print.navitem.jsx'; import PrintNavItem from '../../navbar/print.navitem.jsx';
import RecentNavItems from '../../navbar/recent.navitem.jsx'; import { both as RecentNavItem } from '../../navbar/recent.navitem.jsx';
const { both: RecentNavItem } = RecentNavItems;
// Page specific imports // Page specific imports
import { Meta } from 'vitreum/headtags'; import { Meta } from 'vitreum/headtags';
@@ -55,9 +53,8 @@ const HomePage =(props)=>{
const [isSaving , setIsSaving] = useState(false); const [isSaving , setIsSaving] = useState(false);
const [autoSaveEnabled , setAutoSaveEnable] = useState(false); const [autoSaveEnabled , setAutoSaveEnable] = useState(false);
const editorRef = useRef(null); const editorRef = useRef(null);
const lastSavedBrew = useRef(_.cloneDeep(props.brew)); const lastSavedBrew = useRef(_.cloneDeep(props.brew));
const unsavedChangesRef = useRef(unsavedChanges);
useEffect(()=>{ useEffect(()=>{
fetchThemeBundle(setError, setThemeBundle, currentBrew.renderer, currentBrew.theme); fetchThemeBundle(setError, setThemeBundle, currentBrew.renderer, currentBrew.theme);
@@ -73,20 +70,12 @@ const HomePage =(props)=>{
}; };
document.addEventListener('keydown', handleControlKeys); document.addEventListener('keydown', handleControlKeys);
window.onbeforeunload = ()=>{
if(unsavedChangesRef.current)
return 'You have unsaved changes!';
};
return ()=>{ return ()=>{
document.removeEventListener('keydown', handleControlKeys); document.removeEventListener('keydown', handleControlKeys);
window.onbeforeunload = null;
}; };
}, []); }, []);
useEffect(()=>{
unsavedChangesRef.current = unsavedChanges;
}, [unsavedChanges]);
const save = ()=>{ const save = ()=>{
request.post('/api') request.post('/api')
.send(currentBrew) .send(currentBrew)
@@ -232,4 +221,4 @@ const HomePage =(props)=>{
); );
}; };
export default HomePage; module.exports = HomePage;

View File

@@ -4,17 +4,17 @@ import './newPage.less';
// Common imports // Common imports
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import request from '../../utils/request-middleware.js'; import request from '../../utils/request-middleware.js';
import Markdown from '../../../../shared/markdown.js'; import Markdown from 'markdown.js';
import _ from 'lodash'; 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 SplitPane from '../../../components/splitPane/splitPane.jsx'; import SplitPane from 'client/components/splitPane/splitPane.jsx';
import Editor from '../../editor/editor.jsx'; import Editor from '../../editor/editor.jsx';
import BrewRenderer from '../../brewRenderer/brewRenderer.jsx'; import BrewRenderer from '../../brewRenderer/brewRenderer.jsx';
import Nav from '../../navbar/nav.jsx'; import Nav from 'naturalcrit/nav/nav.jsx';
import Navbar from '../../navbar/navbar.jsx'; import Navbar from '../../navbar/navbar.jsx';
import NewBrewItem from '../../navbar/newbrew.navitem.jsx'; import NewBrewItem from '../../navbar/newbrew.navitem.jsx';
import AccountNavItem from '../../navbar/account.navitem.jsx'; import AccountNavItem from '../../navbar/account.navitem.jsx';
@@ -22,8 +22,7 @@ import ErrorNavItem from '../../navbar/error-navitem.jsx';
import HelpNavItem from '../../navbar/help.navitem.jsx'; import HelpNavItem from '../../navbar/help.navitem.jsx';
import VaultNavItem from '../../navbar/vault.navitem.jsx'; import VaultNavItem from '../../navbar/vault.navitem.jsx';
import PrintNavItem from '../../navbar/print.navitem.jsx'; import PrintNavItem from '../../navbar/print.navitem.jsx';
import RecentNavItems from '../../navbar/recent.navitem.jsx'; import { both as RecentNavItem } from '../../navbar/recent.navitem.jsx';
const { both: RecentNavItem } = RecentNavItems;
// Page specific imports // Page specific imports
import { Meta } from 'vitreum/headtags'; import { Meta } from 'vitreum/headtags';
@@ -57,10 +56,6 @@ const NewPage = (props)=>{
const editorRef = useRef(null); const editorRef = useRef(null);
const lastSavedBrew = useRef(_.cloneDeep(props.brew)); const lastSavedBrew = useRef(_.cloneDeep(props.brew));
// const saveTimeout = useRef(null);
// const warnUnsavedTimeout = useRef(null);
const trySaveRef = useRef(trySave); // CTRL+S listener lives outside React and needs ref to use trySave with latest copy of brew
const unsavedChangesRef = useRef(unsavedChanges); // Similarly, onBeforeUnload lives outside React and needs ref to unsavedChanges
useEffect(()=>{ useEffect(()=>{
loadBrew(); loadBrew();
@@ -119,11 +114,6 @@ const NewPage = (props)=>{
if(autoSaveEnabled) trySave(false, hasChange); if(autoSaveEnabled) trySave(false, hasChange);
}, [currentBrew]); }, [currentBrew]);
useEffect(()=>{
trySaveRef.current = trySave;
unsavedChangesRef.current = unsavedChanges;
});
const handleSplitMove = ()=>{ const handleSplitMove = ()=>{
editorRef.current.update(); editorRef.current.update();
}; };
@@ -151,7 +141,7 @@ const NewPage = (props)=>{
} }
}; };
const trySave = async ()=>{ const save = async ()=>{
setIsSaving(true); setIsSaving(true);
const updatedBrew = { ...currentBrew }; const updatedBrew = { ...currentBrew };
@@ -200,7 +190,7 @@ const NewPage = (props)=>{
// #3 - Unsaved changes exist, click to save, show SAVE NOW // #3 - Unsaved changes exist, click to save, show SAVE NOW
if(unsavedChanges) if(unsavedChanges)
return <Nav.item className='save' onClick={trySave} color='blue' icon='fas fa-save'>save now</Nav.item>; return <Nav.item className='save' onClick={save} color='blue' icon='fas fa-save'>save now</Nav.item>;
// #4 - No unsaved changes, autosave is ON, show AUTO-SAVED // #4 - No unsaved changes, autosave is ON, show AUTO-SAVED
if(autoSaveEnabled) if(autoSaveEnabled)
@@ -277,4 +267,4 @@ const NewPage = (props)=>{
); );
}; };
export default NewPage; module.exports = NewPage;

View File

@@ -1,15 +1,12 @@
.newPage { .newPage {
.navItem.save { .navItem.save {
.fadeInRight();
.transition(opacity);
background-color : @orange; background-color : @orange;
transition:all 0.2s;
&:hover { background-color : @green; } &:hover { background-color : @green; }
&.neverSaved { &.neverSaved {
translate:-100%; .fadeOutRight();
opacity: 0; opacity: 0;
background-color :#333;
cursor:auto;
} }
} }
} }

View File

@@ -1,18 +1,18 @@
import './sharePage.less'; require('./sharePage.less');
import React, { useState, useEffect, useCallback } from 'react'; const React = require('react');
import { Meta } from 'vitreum/headtags'; const { useState, useEffect, useCallback } = React;
const { Meta } = require('vitreum/headtags');
import Nav from '../../navbar/nav.jsx'; const Nav = require('naturalcrit/nav/nav.jsx');
import Navbar from '../../navbar/navbar.jsx'; const Navbar = require('../../navbar/navbar.jsx');
import MetadataNav from '../../navbar/metadata.navitem.jsx'; const MetadataNav = require('../../navbar/metadata.navitem.jsx');
import PrintNavItem from '../../navbar/print.navitem.jsx'; const PrintNavItem = require('../../navbar/print.navitem.jsx');
import RecentNavItems from '../../navbar/recent.navitem.jsx'; const RecentNavItem = require('../../navbar/recent.navitem.jsx').both;
const { both: RecentNavItem } = RecentNavItems; const Account = require('../../navbar/account.navitem.jsx');
import Account from '../../navbar/account.navitem.jsx'; const BrewRenderer = require('../../brewRenderer/brewRenderer.jsx');
import BrewRenderer from '../../brewRenderer/brewRenderer.jsx';
import { DEFAULT_BREW_LOAD } from '../../../../server/brewDefaults.js'; const { DEFAULT_BREW_LOAD } = require('../../../../server/brewDefaults.js');
import { printCurrentBrew, fetchThemeBundle } from '../../../../shared/helpers.js'; const { printCurrentBrew, fetchThemeBundle } = require('../../../../shared/helpers.js');
const SharePage = (props)=>{ const SharePage = (props)=>{
const { brew = DEFAULT_BREW_LOAD, disableMeta = false } = props; const { brew = DEFAULT_BREW_LOAD, disableMeta = false } = props;
@@ -116,4 +116,4 @@ const SharePage = (props)=>{
); );
}; };
export default SharePage; module.exports = SharePage;

View File

@@ -1,17 +1,17 @@
import React, { useState } from 'react'; const React = require('react');
import _ from 'lodash'; const { useState } = React;
const _ = require('lodash');
import ListPage from '../basePages/listPage/listPage.jsx'; const ListPage = require('../basePages/listPage/listPage.jsx');
import Nav from '../../navbar/nav.jsx'; const Nav = require('naturalcrit/nav/nav.jsx');
import Navbar from '../../navbar/navbar.jsx'; const Navbar = require('../../navbar/navbar.jsx');
import RecentNavItems from '../../navbar/recent.navitem.jsx'; const RecentNavItem = require('../../navbar/recent.navitem.jsx').both;
const { both: RecentNavItem } = RecentNavItems; const Account = require('../../navbar/account.navitem.jsx');
import Account from '../../navbar/account.navitem.jsx'; const NewBrew = require('../../navbar/newbrew.navitem.jsx');
import NewBrew from '../../navbar/newbrew.navitem.jsx'; const HelpNavItem = require('../../navbar/help.navitem.jsx');
import HelpNavItem from '../../navbar/help.navitem.jsx'; const ErrorNavItem = require('../../navbar/error-navitem.jsx');
import ErrorNavItem from '../../navbar/error-navitem.jsx'; const VaultNavitem = require('../../navbar/vault.navitem.jsx');
import VaultNavitem from '../../navbar/vault.navitem.jsx';
const UserPage = (props)=>{ const UserPage = (props)=>{
props = { props = {
@@ -61,4 +61,4 @@ const UserPage = (props)=>{
); );
}; };
export default UserPage; module.exports = UserPage;

View File

@@ -1,18 +1,19 @@
/*eslint max-lines: ["warn", {"max": 400, "skipBlankLines": true, "skipComments": true}]*/ /*eslint max-lines: ["warn", {"max": 400, "skipBlankLines": true, "skipComments": true}]*/
/*eslint max-params:["warn", { max: 10 }], */ /*eslint max-params:["warn", { max: 10 }], */
import './vaultPage.less'; require('./vaultPage.less');
import React, { useState, useEffect, useRef } from 'react';
import Nav from '../../navbar/nav.jsx'; const React = require('react');
import Navbar from '../../navbar/navbar.jsx'; const { useState, useEffect, useRef } = React;
import RecentNavItems from '../../navbar/recent.navitem.jsx';
const { both: RecentNavItem } = RecentNavItems; const Nav = require('naturalcrit/nav/nav.jsx');
import Account from '../../navbar/account.navitem.jsx'; const Navbar = require('../../navbar/navbar.jsx');
import NewBrew from '../../navbar/newbrew.navitem.jsx'; const RecentNavItem = require('../../navbar/recent.navitem.jsx').both;
import HelpNavItem from '../../navbar/help.navitem.jsx'; const Account = require('../../navbar/account.navitem.jsx');
import BrewItem from '../basePages/listPage/brewItem/brewItem.jsx'; const NewBrew = require('../../navbar/newbrew.navitem.jsx');
import SplitPane from '../../../components/splitPane/splitPane.jsx'; const HelpNavItem = require('../../navbar/help.navitem.jsx');
import ErrorIndex from '../errorPage/errors/errorIndex.js'; const BrewItem = require('../basePages/listPage/brewItem/brewItem.jsx');
const SplitPane = require('client/components/splitPane/splitPane.jsx');
const ErrorIndex = require('../errorPage/errors/errorIndex.js');
import request from '../../utils/request-middleware.js'; import request from '../../utils/request-middleware.js';
@@ -100,7 +101,7 @@ const VaultPage = (props)=>{
const title = titleRef.current.value || ''; const title = titleRef.current.value || '';
const author = authorRef.current.value || ''; const author = authorRef.current.value || '';
const count = countRef.current.value || 20; const count = countRef.current.value || 10;
const v3 = v3Ref.current.checked != false; const v3 = v3Ref.current.checked != false;
const legacy = legacyRef.current.checked != false; const legacy = legacyRef.current.checked != false;
const sortOption = sort || 'title'; const sortOption = sort || 'title';
@@ -287,8 +288,7 @@ const VaultPage = (props)=>{
const renderPaginationControls = ()=>{ const renderPaginationControls = ()=>{
if(!totalBrews || totalBrews < 10) return null; if(!totalBrews || totalBrews < 10) return null;
const countInt = parseInt(brewCollection.length || 20);
const countInt = parseInt(countRef.current.value || 20);
const totalPages = Math.ceil(totalBrews / countInt); const totalPages = Math.ceil(totalBrews / countInt);
let startPage, endPage; let startPage, endPage;
@@ -429,4 +429,4 @@ const VaultPage = (props)=>{
); );
}; };
export default VaultPage; module.exports = VaultPage;

View File

@@ -32,7 +32,7 @@ export default [{
"max-depth" : ["warn", { max: 4 }], "max-depth" : ["warn", { max: 4 }],
"max-params" : ["warn", { max: 5 }], "max-params" : ["warn", { max: 5 }],
"no-restricted-syntax" : ["warn", "ClassDeclaration", "SwitchStatement"], "no-restricted-syntax" : ["warn", "ClassDeclaration", "SwitchStatement"],
"no-unused-vars" : ["warn", { vars: "all", args: "none", varsIgnorePattern: "config|_|cx|createReactClass" }], "no-unused-vars" : ["warn", { vars: "all", args: "none", varsIgnorePattern: "config|_|cx|createClass" }],
"react/jsx-uses-vars" : "warn", "react/jsx-uses-vars" : "warn",
/** Fixable **/ /** Fixable **/

3373
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -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.20.1", "version": "3.19.3",
"type": "module", "type": "module",
"engines": { "engines": {
"npm": "^10.8.x", "npm": "^10.8.x",
@@ -61,11 +61,8 @@
"server" "server"
], ],
"transformIgnorePatterns": [ "transformIgnorePatterns": [
"node_modules/(?!(nanoid|@exodus/bytes|parse5)/)" "node_modules/(?!nanoid/).*"
], ],
"transform": {
"^.+\\.js$": "babel-jest"
},
"coveragePathIgnorePatterns": [ "coveragePathIgnorePatterns": [
"build/*" "build/*"
], ],
@@ -91,19 +88,19 @@
"@babel/core": "^7.28.4", "@babel/core": "^7.28.4",
"@babel/plugin-transform-runtime": "^7.28.3", "@babel/plugin-transform-runtime": "^7.28.3",
"@babel/preset-env": "^7.28.3", "@babel/preset-env": "^7.28.3",
"@babel/preset-react": "^7.28.5", "@babel/preset-react": "^7.27.1",
"@babel/runtime": "^7.28.4", "@babel/runtime": "^7.28.4",
"@dmsnell/diff-match-patch": "^1.1.0", "@dmsnell/diff-match-patch": "^1.1.0",
"@googleapis/drive": "^19.2.0", "@googleapis/drive": "^18.0.0",
"@sanity/diff-match-patch": "^3.2.0", "@sanity/diff-match-patch": "^3.2.0",
"body-parser": "^2.2.0", "body-parser": "^2.2.0",
"classnames": "^2.5.1", "classnames": "^2.5.1",
"codemirror": "^5.65.6", "codemirror": "^5.65.6",
"cookie-parser": "^1.4.7", "cookie-parser": "^1.4.7",
"core-js": "^3.47.0", "core-js": "^3.46.0",
"cors": "^2.8.5", "cors": "^2.8.5",
"create-react-class": "^15.7.0", "create-react-class": "^15.7.0",
"dedent": "^1.7.1", "dedent-tabs": "^0.10.3",
"expr-eval": "^2.0.2", "expr-eval": "^2.0.2",
"express": "^5.1.0", "express": "^5.1.0",
"express-async-handler": "^1.2.0", "express-async-handler": "^1.2.0",
@@ -112,29 +109,29 @@
"fs-extra": "11.3.2", "fs-extra": "11.3.2",
"hash-wasm": "^4.12.0", "hash-wasm": "^4.12.0",
"idb-keyval": "^6.2.2", "idb-keyval": "^6.2.2",
"js-yaml": "^4.1.1", "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": "15.0.12", "marked": "15.0.12",
"marked-alignment-paragraphs": "^1.0.0", "marked-alignment-paragraphs": "^1.0.0",
"marked-definition-lists": "^1.0.1", "marked-definition-lists": "^1.0.1",
"marked-emoji": "^2.0.2", "marked-emoji": "^2.0.1",
"marked-extended-tables": "^2.0.1", "marked-extended-tables": "^2.0.1",
"marked-gfm-heading-id": "^4.1.3", "marked-gfm-heading-id": "^4.1.2",
"marked-nonbreaking-spaces": "^1.0.1", "marked-nonbreaking-spaces": "^1.0.1",
"marked-smartypants-lite": "^1.0.3", "marked-smartypants-lite": "^1.0.3",
"marked-subsuper-text": "^1.0.4", "marked-subsuper-text": "^1.0.4",
"marked-variables": "^1.0.4", "marked-variables": "^1.0.4",
"markedLegacy": "npm:marked@^0.3.19", "markedLegacy": "npm:marked@^0.3.19",
"moment": "^2.30.1", "moment": "^2.30.1",
"mongoose": "^8.20.0", "mongoose": "^8.19.1",
"nanoid": "5.1.6", "nanoid": "5.1.6",
"nconf": "^0.13.0", "nconf": "^0.13.0",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-frame-component": "^4.1.3", "react-frame-component": "^4.1.3",
"react-router": "^7.9.6", "react-router": "^7.9.4",
"romans": "^3.1.0", "romans": "^3.1.0",
"sanitize-filename": "1.6.3", "sanitize-filename": "1.6.3",
"superagent": "^10.2.1", "superagent": "^10.2.1",
@@ -143,20 +140,18 @@
}, },
"devDependencies": { "devDependencies": {
"@stylistic/stylelint-plugin": "^4.0.0", "@stylistic/stylelint-plugin": "^4.0.0",
"babel-jest": "^30.2.0",
"babel-plugin-transform-import-meta": "^2.3.3", "babel-plugin-transform-import-meta": "^2.3.3",
"eslint": "^9.39.1", "eslint": "^9.39.1",
"eslint-plugin-jest": "^29.1.0", "eslint-plugin-jest": "^29.0.1",
"eslint-plugin-react": "^7.37.5", "eslint-plugin-react": "^7.37.5",
"globals": "^16.4.0", "globals": "^16.4.0",
"jest": "^30.2.0", "jest": "^30.2.0",
"jest-expect-message": "^1.1.3", "jest-expect-message": "^1.1.3",
"jsdom": "^27.4.0",
"jsdom-global": "^3.0.2", "jsdom-global": "^3.0.2",
"postcss-less": "^6.0.0", "postcss-less": "^6.0.0",
"stylelint": "^16.25.0", "stylelint": "^16.25.0",
"stylelint-config-recess-order": "^7.3.0", "stylelint-config-recess-order": "^7.3.0",
"stylelint-config-recommended": "^18.0.0", "stylelint-config-recommended": "^17.0.0",
"supertest": "^7.1.4" "supertest": "^7.1.4"
} }
} }

View File

@@ -6,7 +6,6 @@ import config from './config.js';
let serviceAuth; let serviceAuth;
let clientEmail;
if(!config.get('service_account')){ if(!config.get('service_account')){
const reset = '\x1b[0m'; // Reset to default style const reset = '\x1b[0m'; // Reset to default style
const yellow = '\x1b[33m'; // yellow color const yellow = '\x1b[33m'; // yellow color
@@ -16,10 +15,6 @@ if(!config.get('service_account')){
JSON.parse(config.get('service_account')) : JSON.parse(config.get('service_account')) :
config.get('service_account'); config.get('service_account');
if(keys?.client_email) {
clientEmail = keys.client_email;
}
try { try {
serviceAuth = googleDrive.auth.fromJSON(keys); serviceAuth = googleDrive.auth.fromJSON(keys);
serviceAuth.scopes = ['https://www.googleapis.com/auth/drive']; serviceAuth.scopes = ['https://www.googleapis.com/auth/drive'];
@@ -232,30 +227,14 @@ const GoogleActions = {
if(!obj) return; if(!obj) return;
if(clientEmail) {
await drive.permissions.create({
resource : {
type : 'user',
emailAddress : clientEmail,
role : 'writer'
},
fileId : obj.data.id,
fields : 'id',
})
.catch((err)=>{
console.log('Error adding Service Account permissions on Google Drive file');
console.error(err);
});
}
await drive.permissions.create({ await drive.permissions.create({
resource : { type : 'anyone', resource : { type : 'anyone',
role : 'writer' }, role : 'writer' },
fileId : obj.data.id, fileId : obj.data.id,
fields : 'id', fields : 'id',
}) })
.catch((err)=>{ .catch((err)=>{
console.log('Error adding "Anyone" permissions on Google Drive file'); console.log('Error updating permissions');
console.error(err); console.error(err);
}); });

View File

@@ -8,9 +8,9 @@ import MarkedAlignedParagraphs from 'marked-alignment-paragraphs';
import MarkedNonbreakingSpaces from 'marked-nonbreaking-spaces'; import MarkedNonbreakingSpaces from 'marked-nonbreaking-spaces';
import MarkedSubSuperText from 'marked-subsuper-text'; import MarkedSubSuperText from 'marked-subsuper-text';
import { markedVariables, import { markedVariables,
setMarkedVariablePage, setMarkedVariablePage,
setMarkedVariable, setMarkedVariable,
getMarkedVariable } from 'marked-variables'; getMarkedVariable } from 'marked-variables';
import { markedSmartypantsLite as MarkedSmartypantsLite } from 'marked-smartypants-lite'; import { markedSmartypantsLite as MarkedSmartypantsLite } from 'marked-smartypants-lite';
import { gfmHeadingId as MarkedGFMHeadingId, resetHeadings as MarkedGFMResetHeadingIDs } from 'marked-gfm-heading-id'; import { gfmHeadingId as MarkedGFMHeadingId, resetHeadings as MarkedGFMResetHeadingIDs } from 'marked-gfm-heading-id';
import { markedEmoji as MarkedEmojis } from 'marked-emoji'; import { markedEmoji as MarkedEmojis } from 'marked-emoji';
@@ -31,12 +31,7 @@ renderer.html = function (token) {
const openTag = html.substring(0, html.indexOf('>')+1); const openTag = html.substring(0, html.indexOf('>')+1);
html = html.substring(html.indexOf('>')+1); html = html.substring(html.indexOf('>')+1);
html = html.substring(0, html.lastIndexOf('</div>')); html = html.substring(0, html.lastIndexOf('</div>'));
return `${openTag} ${Marked.parse(html)} </div>`;
// Repeat the markdown processing for content inside the div, minus the preprocessing and postprocessing hooks which should only run once globally
const opts = Marked.defaults;
const tokens = Marked.lexer(html, opts);
Marked.walkTokens(tokens, opts.walkTokens);
return `${openTag} ${Marked.parser(tokens, opts)} </div>`;
} }
return html; return html;
}; };

View File

@@ -1,5 +1,5 @@
import _ from 'lodash'; const _ = require('lodash');
import Markdown from 'markedLegacy'; const Markdown = require('markedLegacy');
const renderer = new Markdown.Renderer(); const renderer = new Markdown.Renderer();
//Processes the markdown within an HTML block if it's just a class-wrapper //Processes the markdown within an HTML block if it's just a class-wrapper
@@ -103,7 +103,7 @@ const voidTags = new Set([
]); ]);
export default { module.exports = {
marked : Markdown, marked : Markdown,
render : (rawBrewText)=>{ render : (rawBrewText)=>{
return Markdown( return Markdown(

View File

@@ -79,6 +79,6 @@ const showAutocompleteEmoji = function(CodeMirror, editor) {
}); });
}; };
export default { module.exports = {
showAutocompleteEmoji showAutocompleteEmoji
}; };

View File

@@ -38,11 +38,11 @@ const autoCloseCurlyBraces = function(CodeMirror, cm, typingClosingBrace) {
} }
}; };
export default { module.exports = {
autoCloseCurlyBraces : function(CodeMirror, codeMirror) { autoCloseCurlyBraces : function(CodeMirror, codeMirror) {
const map = { name: 'autoCloseCurlyBraces' }; const map = { name: 'autoCloseCurlyBraces' };
map[`'{'`] = function(cm) { return autoCloseCurlyBraces(CodeMirror, cm); }; map[`'{'`] = function(cm) { return autoCloseCurlyBraces(CodeMirror, cm); };
map[`'}'`] = function(cm) { return autoCloseCurlyBraces(CodeMirror, cm, true); }; map[`'}'`] = function(cm) { return autoCloseCurlyBraces(CodeMirror, cm, true); };
codeMirror?.addKeyMap(map); codeMirror.addKeyMap(map);
} }
}; };

View File

@@ -1,13 +1,51 @@
/* eslint-disable max-lines */ /* eslint-disable max-lines */
import './codeEditor.less'; require('./codeEditor.less');
import React from 'react'; const React = require('react');
import createReactClass from 'create-react-class'; const createClass = require('create-react-class');
import _ from 'lodash'; const _ = require('lodash');
import closeTag from './close-tag'; const closeTag = require('./close-tag');
import autoCompleteEmoji from './autocompleteEmoji'; const autoCompleteEmoji = require('./autocompleteEmoji');
let CodeMirror;
const CodeEditor = createReactClass({ let CodeMirror;
if(typeof window !== 'undefined'){
CodeMirror = require('codemirror');
//Language Modes
require('codemirror/mode/gfm/gfm.js'); //Github flavoured markdown
require('codemirror/mode/css/css.js');
require('codemirror/mode/javascript/javascript.js');
//Addons
//Code folding
require('codemirror/addon/fold/foldcode.js');
require('codemirror/addon/fold/foldgutter.js');
//Search and replace
require('codemirror/addon/search/search.js');
require('codemirror/addon/search/searchcursor.js');
require('codemirror/addon/search/jump-to-line.js');
require('codemirror/addon/search/match-highlighter.js');
require('codemirror/addon/search/matchesonscrollbar.js');
require('codemirror/addon/dialog/dialog.js');
//Trailing space highlighting
// require('codemirror/addon/edit/trailingspace.js');
//Active line highlighting
// require('codemirror/addon/selection/active-line.js');
//Scroll past last line
require('codemirror/addon/scroll/scrollpastend.js');
//Auto-closing
//XML code folding is a requirement of the auto-closing tag feature and is not enabled
require('codemirror/addon/fold/xml-fold.js');
require('codemirror/addon/edit/closetag.js');
//Autocompletion
require('codemirror/addon/hint/show-hint.js');
const foldPagesCode = require('./fold-pages');
foldPagesCode.registerHomebreweryHelper(CodeMirror);
const foldCSSCode = require('./fold-css');
foldCSSCode.registerHomebreweryHelper(CodeMirror);
}
const CodeEditor = createClass({
displayName : 'CodeEditor', displayName : 'CodeEditor',
getDefaultProps : function() { getDefaultProps : function() {
return { return {
@@ -28,54 +66,23 @@ const CodeEditor = createReactClass({
editor : React.createRef(null), editor : React.createRef(null),
async componentDidMount() { componentDidMount : function() {
CodeMirror = (await import('codemirror')).default;
this.CodeMirror = CodeMirror;
await import('codemirror/mode/gfm/gfm.js');
await import('codemirror/mode/css/css.js');
await import('codemirror/mode/javascript/javascript.js');
// addons
await import('codemirror/addon/fold/foldcode.js');
await import('codemirror/addon/fold/foldgutter.js');
await import('codemirror/addon/fold/xml-fold.js');
await import('codemirror/addon/search/search.js');
await import('codemirror/addon/search/searchcursor.js');
await import('codemirror/addon/search/jump-to-line.js');
await import('codemirror/addon/search/match-highlighter.js');
await import('codemirror/addon/search/matchesonscrollbar.js');
await import('codemirror/addon/dialog/dialog.js');
await import('codemirror/addon/scroll/scrollpastend.js');
await import('codemirror/addon/edit/closetag.js');
await import('codemirror/addon/hint/show-hint.js');
// import 'codemirror/addon/selection/active-line.js';
// import 'codemirror/addon/edit/trailingspace.js';
// register helpers dynamically as well
const foldPagesCode = (await import('./fold-pages')).default;
const foldCSSCode = (await import('./fold-css')).default;
foldPagesCode.registerHomebreweryHelper(CodeMirror);
foldCSSCode.registerHomebreweryHelper(CodeMirror);
this.buildEditor(); this.buildEditor();
const newDoc = CodeMirror?.Doc(this.props.value, this.props.language); const newDoc = CodeMirror.Doc(this.props.value, this.props.language);
this.codeMirror?.swapDoc(newDoc); this.codeMirror.swapDoc(newDoc);
}, },
componentDidUpdate : function(prevProps) { componentDidUpdate : function(prevProps) {
if(prevProps.view !== this.props.view){ //view changed; swap documents if(prevProps.view !== this.props.view){ //view changed; swap documents
let newDoc; let newDoc;
if(!this.state.docs[this.props.view]) { if(!this.state.docs[this.props.view]) {
newDoc = CodeMirror?.Doc(this.props.value, this.props.language); newDoc = CodeMirror.Doc(this.props.value, this.props.language);
} else { } else {
newDoc = this.state.docs[this.props.view]; newDoc = this.state.docs[this.props.view];
} }
const oldDoc = { [prevProps.view]: this.codeMirror?.swapDoc(newDoc) }; const oldDoc = { [prevProps.view]: this.codeMirror.swapDoc(newDoc) };
this.setState((prevState)=>({ this.setState((prevState)=>({
docs : _.merge({}, prevState.docs, oldDoc) docs : _.merge({}, prevState.docs, oldDoc)
@@ -83,17 +90,17 @@ const CodeEditor = createReactClass({
this.props.rerenderParent(); this.props.rerenderParent();
} else if(this.codeMirror?.getValue() != this.props.value) { //update editor contents if brew.text is changed from outside } else if(this.codeMirror?.getValue() != this.props.value) { //update editor contents if brew.text is changed from outside
this.codeMirror?.setValue(this.props.value); this.codeMirror.setValue(this.props.value);
} }
if(this.props.enableFolding) { if(this.props.enableFolding) {
this.codeMirror?.setOption('foldOptions', this.foldOptions(this.codeMirror)); this.codeMirror.setOption('foldOptions', this.foldOptions(this.codeMirror));
} else { } else {
this.codeMirror?.setOption('foldOptions', false); this.codeMirror.setOption('foldOptions', false);
} }
if(prevProps.editorTheme !== this.props.editorTheme){ if(prevProps.editorTheme !== this.props.editorTheme){
this.codeMirror?.setOption('theme', this.props.editorTheme); this.codeMirror.setOption('theme', this.props.editorTheme);
} }
}, },
@@ -181,8 +188,8 @@ const CodeEditor = createReactClass({
closeTag.autoCloseCurlyBraces(CodeMirror, this.codeMirror); closeTag.autoCloseCurlyBraces(CodeMirror, this.codeMirror);
autoCompleteEmoji.showAutocompleteEmoji(CodeMirror, this.codeMirror); autoCompleteEmoji.showAutocompleteEmoji(CodeMirror, this.codeMirror);
// Note: codeMirror passes a copy of itself in this callback. cm === this.codeMirror?. Either one works. // Note: codeMirror passes a copy of itself in this callback. cm === this.codeMirror. Either one works.
this.codeMirror?.on('change', (cm)=>{this.props.onChange(cm.getValue());}); this.codeMirror.on('change', (cm)=>{this.props.onChange(cm.getValue());});
this.updateSize(); this.updateSize();
}, },
@@ -196,84 +203,84 @@ const CodeEditor = createReactClass({
}, },
dedent : function () { dedent : function () {
this.codeMirror?.execCommand('indentLess'); this.codeMirror.execCommand('indentLess');
}, },
makeHeader : function (number) { makeHeader : function (number) {
const selection = this.codeMirror?.getSelection(); const selection = this.codeMirror.getSelection();
const header = Array(number).fill('#').join(''); const header = Array(number).fill('#').join('');
this.codeMirror?.replaceSelection(`${header} ${selection}`, 'around'); this.codeMirror.replaceSelection(`${header} ${selection}`, 'around');
const cursor = this.codeMirror?.getCursor(); const cursor = this.codeMirror.getCursor();
this.codeMirror?.setCursor({ line: cursor.line, ch: cursor.ch + selection.length + number + 1 }); this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch + selection.length + number + 1 });
}, },
makeBold : function() { makeBold : function() {
const selection = this.codeMirror?.getSelection(), t = selection.slice(0, 2) === '**' && selection.slice(-2) === '**'; const selection = this.codeMirror.getSelection(), t = selection.slice(0, 2) === '**' && selection.slice(-2) === '**';
this.codeMirror?.replaceSelection(t ? selection.slice(2, -2) : `**${selection}**`, 'around'); this.codeMirror.replaceSelection(t ? selection.slice(2, -2) : `**${selection}**`, 'around');
if(selection.length === 0){ if(selection.length === 0){
const cursor = this.codeMirror?.getCursor(); const cursor = this.codeMirror.getCursor();
this.codeMirror?.setCursor({ line: cursor.line, ch: cursor.ch - 2 }); this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - 2 });
} }
}, },
makeItalic : function() { makeItalic : function() {
const selection = this.codeMirror?.getSelection(), t = selection.slice(0, 1) === '*' && selection.slice(-1) === '*'; const selection = this.codeMirror.getSelection(), t = selection.slice(0, 1) === '*' && selection.slice(-1) === '*';
this.codeMirror?.replaceSelection(t ? selection.slice(1, -1) : `*${selection}*`, 'around'); this.codeMirror.replaceSelection(t ? selection.slice(1, -1) : `*${selection}*`, 'around');
if(selection.length === 0){ if(selection.length === 0){
const cursor = this.codeMirror?.getCursor(); const cursor = this.codeMirror.getCursor();
this.codeMirror?.setCursor({ line: cursor.line, ch: cursor.ch - 1 }); this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - 1 });
} }
}, },
makeSuper : function() { makeSuper : function() {
const selection = this.codeMirror?.getSelection(), t = selection.slice(0, 1) === '^' && selection.slice(-1) === '^'; const selection = this.codeMirror.getSelection(), t = selection.slice(0, 1) === '^' && selection.slice(-1) === '^';
this.codeMirror?.replaceSelection(t ? selection.slice(1, -1) : `^${selection}^`, 'around'); this.codeMirror.replaceSelection(t ? selection.slice(1, -1) : `^${selection}^`, 'around');
if(selection.length === 0){ if(selection.length === 0){
const cursor = this.codeMirror?.getCursor(); const cursor = this.codeMirror.getCursor();
this.codeMirror?.setCursor({ line: cursor.line, ch: cursor.ch - 1 }); this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - 1 });
} }
}, },
makeSub : function() { makeSub : function() {
const selection = this.codeMirror?.getSelection(), t = selection.slice(0, 2) === '^^' && selection.slice(-2) === '^^'; const selection = this.codeMirror.getSelection(), t = selection.slice(0, 2) === '^^' && selection.slice(-2) === '^^';
this.codeMirror?.replaceSelection(t ? selection.slice(2, -2) : `^^${selection}^^`, 'around'); this.codeMirror.replaceSelection(t ? selection.slice(2, -2) : `^^${selection}^^`, 'around');
if(selection.length === 0){ if(selection.length === 0){
const cursor = this.codeMirror?.getCursor(); const cursor = this.codeMirror.getCursor();
this.codeMirror?.setCursor({ line: cursor.line, ch: cursor.ch - 2 }); this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - 2 });
} }
}, },
makeNbsp : function() { makeNbsp : function() {
this.codeMirror?.replaceSelection('&nbsp;', 'end'); this.codeMirror.replaceSelection('&nbsp;', 'end');
}, },
makeSpace : function() { makeSpace : function() {
const selection = this.codeMirror?.getSelection(); const selection = this.codeMirror.getSelection();
const t = selection.slice(0, 8) === '{{width:' && selection.slice(0 -4) === '% }}'; const t = selection.slice(0, 8) === '{{width:' && selection.slice(0 -4) === '% }}';
if(t){ if(t){
const percent = parseInt(selection.slice(8, -4)) + 10; const percent = parseInt(selection.slice(8, -4)) + 10;
this.codeMirror?.replaceSelection(percent < 90 ? `{{width:${percent}% }}` : '{{width:100% }}', 'around'); this.codeMirror.replaceSelection(percent < 90 ? `{{width:${percent}% }}` : '{{width:100% }}', 'around');
} else { } else {
this.codeMirror?.replaceSelection(`{{width:10% }}`, 'around'); this.codeMirror.replaceSelection(`{{width:10% }}`, 'around');
} }
}, },
removeSpace : function() { removeSpace : function() {
const selection = this.codeMirror?.getSelection(); const selection = this.codeMirror.getSelection();
const t = selection.slice(0, 8) === '{{width:' && selection.slice(0 -4) === '% }}'; const t = selection.slice(0, 8) === '{{width:' && selection.slice(0 -4) === '% }}';
if(t){ if(t){
const percent = parseInt(selection.slice(8, -4)) - 10; const percent = parseInt(selection.slice(8, -4)) - 10;
this.codeMirror?.replaceSelection(percent > 10 ? `{{width:${percent}% }}` : '', 'around'); this.codeMirror.replaceSelection(percent > 10 ? `{{width:${percent}% }}` : '', 'around');
} }
}, },
newColumn : function() { newColumn : function() {
this.codeMirror?.replaceSelection('\n\\column\n\n', 'end'); this.codeMirror.replaceSelection('\n\\column\n\n', 'end');
}, },
newPage : function() { newPage : function() {
this.codeMirror?.replaceSelection('\n\\page\n\n', 'end'); this.codeMirror.replaceSelection('\n\\page\n\n', 'end');
}, },
injectText : function(injectText, overwrite=true) { injectText : function(injectText, overwrite=true) {
@@ -286,29 +293,29 @@ const CodeEditor = createReactClass({
}, },
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');
if(selection.length === 0){ if(selection.length === 0){
const cursor = this.codeMirror?.getCursor(); const cursor = this.codeMirror.getCursor();
this.codeMirror?.setCursor({ line: cursor.line, ch: cursor.ch - 4 }); this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - 4 });
} }
}, },
makeSpan : function() { makeSpan : function() {
const selection = this.codeMirror?.getSelection(), t = selection.slice(0, 2) === '{{' && selection.slice(-2) === '}}'; const selection = this.codeMirror.getSelection(), t = selection.slice(0, 2) === '{{' && selection.slice(-2) === '}}';
this.codeMirror?.replaceSelection(t ? selection.slice(2, -2) : `{{ ${selection}}}`, 'around'); this.codeMirror.replaceSelection(t ? selection.slice(2, -2) : `{{ ${selection}}}`, 'around');
if(selection.length === 0){ if(selection.length === 0){
const cursor = this.codeMirror?.getCursor(); const cursor = this.codeMirror.getCursor();
this.codeMirror?.setCursor({ line: cursor.line, ch: cursor.ch - 2 }); this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - 2 });
} }
}, },
makeDiv : function() { makeDiv : function() {
const selection = this.codeMirror?.getSelection(), t = selection.slice(0, 2) === '{{' && selection.slice(-2) === '}}'; const selection = this.codeMirror.getSelection(), t = selection.slice(0, 2) === '{{' && selection.slice(-2) === '}}';
this.codeMirror?.replaceSelection(t ? selection.slice(2, -2) : `{{\n${selection}\n}}`, 'around'); this.codeMirror.replaceSelection(t ? selection.slice(2, -2) : `{{\n${selection}\n}}`, 'around');
if(selection.length === 0){ if(selection.length === 0){
const cursor = this.codeMirror?.getCursor(); const cursor = this.codeMirror.getCursor();
this.codeMirror?.setCursor({ line: cursor.line - 1, ch: cursor.ch }); // set to -2? if wanting to enter classes etc. if so, get rid of first \n when replacing selection this.codeMirror.setCursor({ line: cursor.line - 1, ch: cursor.ch }); // set to -2? if wanting to enter classes etc. if so, get rid of first \n when replacing selection
} }
}, },
@@ -316,7 +323,7 @@ const CodeEditor = createReactClass({
let regex; let regex;
let cursorPos; let cursorPos;
let newComment; let newComment;
const selection = this.codeMirror?.getSelection(); const selection = this.codeMirror.getSelection();
if(this.props.language === 'gfm'){ if(this.props.language === 'gfm'){
regex = /^\s*(<!--\s?)(.*?)(\s?-->)\s*$/gs; regex = /^\s*(<!--\s?)(.*?)(\s?-->)\s*$/gs;
cursorPos = 4; cursorPos = 4;
@@ -326,44 +333,44 @@ const CodeEditor = createReactClass({
cursorPos = 3; cursorPos = 3;
newComment = `/* ${selection} */`; newComment = `/* ${selection} */`;
} }
this.codeMirror?.replaceSelection(regex.test(selection) == true ? selection.replace(regex, '$2') : newComment, 'around'); this.codeMirror.replaceSelection(regex.test(selection) == true ? selection.replace(regex, '$2') : newComment, 'around');
if(selection.length === 0){ if(selection.length === 0){
const cursor = this.codeMirror?.getCursor(); const cursor = this.codeMirror.getCursor();
this.codeMirror?.setCursor({ line: cursor.line, ch: cursor.ch - cursorPos }); this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - cursorPos });
}; };
}, },
makeLink : function() { makeLink : function() {
const isLink = /^\[(.*)\]\((.*)\)$/; const isLink = /^\[(.*)\]\((.*)\)$/;
const selection = this.codeMirror?.getSelection().trim(); const selection = this.codeMirror.getSelection().trim();
let match; let match;
if(match = isLink.exec(selection)){ if(match = isLink.exec(selection)){
const altText = match[1]; const altText = match[1];
const url = match[2]; const url = match[2];
this.codeMirror?.replaceSelection(`${altText} ${url}`); this.codeMirror.replaceSelection(`${altText} ${url}`);
const cursor = this.codeMirror?.getCursor(); const cursor = this.codeMirror.getCursor();
this.codeMirror?.setSelection({ line: cursor.line, ch: cursor.ch - url.length }, { line: cursor.line, ch: cursor.ch }); this.codeMirror.setSelection({ line: cursor.line, ch: cursor.ch - url.length }, { line: cursor.line, ch: cursor.ch });
} else { } else {
this.codeMirror?.replaceSelection(`[${selection || 'alt text'}](url)`); this.codeMirror.replaceSelection(`[${selection || 'alt text'}](url)`);
const cursor = this.codeMirror?.getCursor(); const cursor = this.codeMirror.getCursor();
this.codeMirror?.setSelection({ line: cursor.line, ch: cursor.ch - 4 }, { line: cursor.line, ch: cursor.ch - 1 }); this.codeMirror.setSelection({ line: cursor.line, ch: cursor.ch - 4 }, { line: cursor.line, ch: cursor.ch - 1 });
} }
}, },
makeList : function(listType) { makeList : function(listType) {
const selectionStart = this.codeMirror?.getCursor('from'), selectionEnd = this.codeMirror?.getCursor('to'); const selectionStart = this.codeMirror.getCursor('from'), selectionEnd = this.codeMirror.getCursor('to');
this.codeMirror?.setSelection( this.codeMirror.setSelection(
{ line: selectionStart.line, ch: 0 }, { line: selectionStart.line, ch: 0 },
{ line: selectionEnd.line, ch: this.codeMirror?.getLine(selectionEnd.line).length } { line: selectionEnd.line, ch: this.codeMirror.getLine(selectionEnd.line).length }
); );
const newSelection = this.codeMirror?.getSelection(); const newSelection = this.codeMirror.getSelection();
const regex = /^\d+\.\s|^-\s/gm; const regex = /^\d+\.\s|^-\s/gm;
if(newSelection.match(regex) != null){ // if selection IS A LIST if(newSelection.match(regex) != null){ // if selection IS A LIST
this.codeMirror?.replaceSelection(newSelection.replace(regex, ''), 'around'); this.codeMirror.replaceSelection(newSelection.replace(regex, ''), 'around');
} else { // if selection IS NOT A LIST } else { // if selection IS NOT A LIST
listType == 'UL' ? this.codeMirror?.replaceSelection(newSelection.replace(/^/gm, `- `), 'around') : listType == 'UL' ? this.codeMirror.replaceSelection(newSelection.replace(/^/gm, `- `), 'around') :
this.codeMirror?.replaceSelection(newSelection.replace(/^/gm, (()=>{ this.codeMirror.replaceSelection(newSelection.replace(/^/gm, (()=>{
let n = 1; let n = 1;
return ()=>{ return ()=>{
return `${n++}. `; return `${n++}. `;
@@ -373,39 +380,39 @@ const CodeEditor = createReactClass({
}, },
foldAllCode : function() { foldAllCode : function() {
this.codeMirror?.execCommand('foldAll'); this.codeMirror.execCommand('foldAll');
}, },
unfoldAllCode : function() { unfoldAllCode : function() {
this.codeMirror?.execCommand('unfoldAll'); this.codeMirror.execCommand('unfoldAll');
}, },
//=-- Externally used -==// //=-- Externally used -==//
setCursorPosition : function(line, char){ setCursorPosition : function(line, char){
setTimeout(()=>{ setTimeout(()=>{
this.codeMirror?.focus(); this.codeMirror.focus();
this.codeMirror?.doc.setCursor(line, char); this.codeMirror.doc.setCursor(line, char);
}, 10); }, 10);
}, },
getCursorPosition : function(){ getCursorPosition : function(){
return this.codeMirror?.getCursor(); return this.codeMirror.getCursor();
}, },
getTopVisibleLine : function(){ getTopVisibleLine : function(){
const rect = this.codeMirror?.getWrapperElement().getBoundingClientRect(); const rect = this.codeMirror.getWrapperElement().getBoundingClientRect();
const topVisibleLine = this.codeMirror?.lineAtHeight(rect.top, 'window'); const topVisibleLine = this.codeMirror.lineAtHeight(rect.top, 'window');
return topVisibleLine; return topVisibleLine;
}, },
updateSize : function(){ updateSize : function(){
this.codeMirror?.refresh(); this.codeMirror.refresh();
}, },
redo : function(){ redo : function(){
return this.codeMirror?.redo(); return this.codeMirror.redo();
}, },
undo : function(){ undo : function(){
return this.codeMirror?.undo(); return this.codeMirror.undo();
}, },
historySize : function(){ historySize : function(){
return this.codeMirror?.doc.historySize(); return this.codeMirror.doc.historySize();
}, },
foldOptions : function(cm){ foldOptions : function(cm){
@@ -419,7 +426,7 @@ const CodeEditor = createReactClass({
let foldPreviewText = ''; let foldPreviewText = '';
while (currentLine <= to.line && text.length <= maxLength) { while (currentLine <= to.line && text.length <= maxLength) {
const currentText = this.codeMirror?.getLine(currentLine); const currentText = this.codeMirror.getLine(currentLine);
currentLine++; currentLine++;
if(currentText[0] == '#'){ if(currentText[0] == '#'){
foldPreviewText = currentText; foldPreviewText = currentText;
@@ -454,5 +461,5 @@ const CodeEditor = createReactClass({
} }
}); });
export default CodeEditor; module.exports = CodeEditor;

View File

@@ -1,4 +1,4 @@
export default { module.exports = {
registerHomebreweryHelper : function(CodeMirror) { registerHomebreweryHelper : function(CodeMirror) {
CodeMirror.registerHelper('fold', 'homebrewerycss', function(cm, start) { CodeMirror.registerHelper('fold', 'homebrewerycss', function(cm, start) {

View File

@@ -1,4 +1,4 @@
export default { module.exports = {
registerHomebreweryHelper : function(CodeMirror) { registerHomebreweryHelper : function(CodeMirror) {
CodeMirror.registerHelper('fold', 'homebrewery', function(cm, start) { CodeMirror.registerHelper('fold', 'homebrewery', function(cm, start) {
const matcher = /^\\page.*/; const matcher = /^\\page.*/;

View File

@@ -1,13 +1,14 @@
import './navbar.less'; require('client/homebrew/navbar/navbar.less');
import React, { useState, useRef, useEffect } from 'react'; const React = require('react');
import createReactClass from 'create-react-class'; const { useState, useRef, useEffect } = React;
import _ from 'lodash'; const createClass = require('create-react-class');
import cx from 'classnames'; const _ = require('lodash');
const cx = require('classnames');
import NaturalCritIcon from '../../components/svg/naturalcrit-d20.svg.jsx'; const NaturalCritIcon = require('client/components/svg/naturalcrit-d20.svg.jsx');
const Nav = { const Nav = {
base : createReactClass({ base : createClass({
displayName : 'Nav.base', displayName : 'Nav.base',
render : function(){ render : function(){
return <nav> return <nav>
@@ -24,7 +25,7 @@ const Nav = {
</a>; </a>;
}, },
section : createReactClass({ section : createClass({
displayName : 'Nav.section', displayName : 'Nav.section',
render : function(){ render : function(){
return <div className={`navSection ${this.props.className ?? ''}`}> return <div className={`navSection ${this.props.className ?? ''}`}>
@@ -33,7 +34,7 @@ const Nav = {
} }
}), }),
item : createReactClass({ item : createClass({
displayName : 'Nav.item', displayName : 'Nav.item',
getDefaultProps : function() { getDefaultProps : function() {
return { return {
@@ -116,4 +117,4 @@ const Nav = {
}; };
export default Nav; module.exports = Nav;

View File

@@ -1,5 +1,7 @@
import globalJsdom from 'jsdom-global';
globalJsdom();
require('jsdom-global')();
import { safeHTML } from '../../client/homebrew/brewRenderer/safeHTML'; import { safeHTML } from '../../client/homebrew/brewRenderer/safeHTML';
test('Exit if no document', function() { test('Exit if no document', function() {

View File

@@ -1,5 +1,5 @@
import Markdown from 'markdown.js'; import Markdown from 'markdown.js';
import dedent from 'dedent'; const dedent = require('dedent-tabs').default;
// Marked.js adds line returns after closing tags on some default tokens. // Marked.js adds line returns after closing tags on some default tokens.
// This removes those line returns for comparison sake. // This removes those line returns for comparison sake.

View File

@@ -1,6 +1,6 @@
/* eslint-disable max-lines */ /* eslint-disable max-lines */
import dedent from 'dedent'; const dedent = require('dedent-tabs').default;
import Markdown from 'markdown.js'; import Markdown from 'markdown.js';
// Marked.js adds line returns after closing tags on some default tokens. // Marked.js adds line returns after closing tags on some default tokens.

View File

@@ -1,6 +1,6 @@
/* eslint-disable max-lines */ /* eslint-disable max-lines */
import dedent from 'dedent'; const dedent = require('dedent-tabs').default;
import Markdown from 'markdown.js'; import Markdown from 'markdown.js';
// Marked.js adds line returns after closing tags on some default tokens. // Marked.js adds line returns after closing tags on some default tokens.

View File

@@ -1,14 +1,14 @@
/* eslint-disable max-lines */ /* eslint-disable max-lines */
import MagicGen from './snippets/magic.gen.js'; const MagicGen = require('./snippets/magic.gen.js');
import ClassTableGen from './snippets/classtable.gen.js'; const ClassTableGen = require('./snippets/classtable.gen.js');
import MonsterBlockGen from './snippets/monsterblock.gen.js'; const MonsterBlockGen = require('./snippets/monsterblock.gen.js');
import ClassFeatureGen from './snippets/classfeature.gen.js'; const ClassFeatureGen = require('./snippets/classfeature.gen.js');
import CoverPageGen from './snippets/coverpage.gen.js'; const CoverPageGen = require('./snippets/coverpage.gen.js');
import TableOfContentsGen from './snippets/tableOfContents.gen.js'; const TableOfContentsGen = require('./snippets/tableOfContents.gen.js');
import dedent from 'dedent'; const dedent = require('dedent-tabs').default;
export default [ module.exports = [
{ {
groupName : 'Text Editor', groupName : 'Text Editor',

View File

@@ -1,6 +1,6 @@
import _ from 'lodash'; const _ = require('lodash');
export default function(classname){ module.exports = function(classname){
classname = _.sample(['archivist', 'fancyman', 'linguist', 'fletcher', classname = _.sample(['archivist', 'fancyman', 'linguist', 'fletcher',
'notary', 'berserker-typist', 'fishmongerer', 'manicurist', 'haberdasher', 'concierge']); 'notary', 'berserker-typist', 'fishmongerer', 'manicurist', 'haberdasher', 'concierge']);

View File

@@ -1,4 +1,4 @@
import _ from 'lodash'; const _ = require('lodash');
const features = [ const features = [
'Astrological Botany', 'Astrological Botany',
@@ -50,7 +50,7 @@ const getFeature = (level)=>{
return res.join(', '); return res.join(', ');
}; };
export default { module.exports = {
full : function(){ full : function(){
const classname = _.sample(classnames); const classname = _.sample(classnames);

View File

@@ -1,4 +1,4 @@
import _ from 'lodash'; const _ = require('lodash');
const titles = [ const titles = [
'The Burning Gallows', 'The Burning Gallows',
@@ -98,7 +98,7 @@ const subtitles = [
]; ];
export default ()=>{ module.exports = ()=>{
return `<style> return `<style>
.phb#p1{ text-align:center; } .phb#p1{ text-align:center; }
.phb#p1:after{ display:none; } .phb#p1:after{ display:none; }

View File

@@ -1,10 +1,10 @@
import _ from 'lodash'; const _ = require('lodash');
import ClassFeatureGen from './classfeature.gen.js'; const ClassFeatureGen = require('./classfeature.gen.js');
import ClassTableGen from './classtable.gen.js'; const ClassTableGen = require('./classtable.gen.js');
export default function(){ module.exports = function(){
const classname = _.sample(['Archivist', 'Fancyman', 'Linguist', 'Fletcher', const classname = _.sample(['Archivist', 'Fancyman', 'Linguist', 'Fletcher',
'Notary', 'Berserker-Typist', 'Fishmongerer', 'Manicurist', 'Haberdasher', 'Concierge']); 'Notary', 'Berserker-Typist', 'Fishmongerer', 'Manicurist', 'Haberdasher', 'Concierge']);

View File

@@ -1,4 +1,4 @@
import _ from 'lodash'; const _ = require('lodash');
const spellNames = [ const spellNames = [
'Astral Rite of Acne', 'Astral Rite of Acne',
@@ -48,7 +48,7 @@ const spellNames = [
'Ultimate Ritual of Mouthwash', 'Ultimate Ritual of Mouthwash',
]; ];
export default { module.exports = {
spellList : function(){ spellList : function(){
const levels = ['Cantrips (0 Level)', '1st Level', '2nd Level', '3rd Level', '4th Level', '5th Level', '6th Level', '7th Level', '8th Level', '9th Level']; const levels = ['Cantrips (0 Level)', '1st Level', '2nd Level', '3rd Level', '4th Level', '5th Level', '6th Level', '7th Level', '8th Level', '9th Level'];

View File

@@ -1,4 +1,4 @@
import _ from 'lodash'; const _ = require('lodash');
const genList = function(list, max){ const genList = function(list, max){
return _.sampleSize(list, _.random(0, max)).join(', ') || 'None'; return _.sampleSize(list, _.random(0, max)).join(', ') || 'None';
@@ -137,7 +137,7 @@ const genAction = function(){
}; };
export default { module.exports = {
full : function(){ full : function(){
return `${[ return `${[

View File

@@ -1,4 +1,4 @@
import _ from 'lodash'; const _ = require('lodash');
const getTOC = (pages)=>{ const getTOC = (pages)=>{
const add1 = (title, page)=>{ const add1 = (title, page)=>{
@@ -47,7 +47,7 @@ const getTOC = (pages)=>{
return res; return res;
}; };
export default function(props){ module.exports = function(props){
const pages = props.brew.text.split('\\page'); const pages = props.brew.text.split('\\page');
const TOC = getTOC(pages); const TOC = getTOC(pages);
const markdown = _.reduce(TOC, (r, g1, idx1)=>{ const markdown = _.reduce(TOC, (r, g1, idx1)=>{

View File

@@ -1,4 +1,4 @@
export default [ module.exports = [
]; ];

View File

@@ -1,14 +1,17 @@
/* eslint-disable max-lines */ /* eslint-disable max-lines */
import MagicGen from './snippets/magic.gen.js';
import ClassTableGen from './snippets/classtable.gen.js';
import MonsterBlockGen from './snippets/monsterblock.gen.js';
import scriptGen from './snippets/script.gen.js';
import ClassFeatureGen from './snippets/classfeature.gen.js';
import CoverPageGen from './snippets/coverpage.gen.js';
import QuoteGen from './snippets/quote.gen.js';
import dedent from 'dedent';
export default [ const MagicGen = require('./snippets/magic.gen.js');
const ClassTableGen = require('./snippets/classtable.gen.js');
const MonsterBlockGen = require('./snippets/monsterblock.gen.js');
const scriptGen = require('./snippets/script.gen.js');
const ClassFeatureGen = require('./snippets/classfeature.gen.js');
const CoverPageGen = require('./snippets/coverpage.gen.js');
const QuoteGen = require('./snippets/quote.gen.js');
const dedent = require('dedent-tabs').default;
module.exports = [
{ {
groupName : 'Style Editor', groupName : 'Style Editor',
icon : 'fas fa-pencil-alt', icon : 'fas fa-pencil-alt',

View File

@@ -1,7 +1,7 @@
import _ from 'lodash'; const _ = require('lodash');
import dedent from 'dedent'; const dedent = require('dedent-tabs').default;
export default function(classname){ module.exports = function(classname){
classname = _.sample(['archivist', 'fancyman', 'linguist', 'fletcher', classname = _.sample(['archivist', 'fancyman', 'linguist', 'fletcher',
'notary', 'berserker-typist', 'fishmongerer', 'manicurist', 'haberdasher', 'concierge']); 'notary', 'berserker-typist', 'fishmongerer', 'manicurist', 'haberdasher', 'concierge']);

View File

@@ -1,5 +1,5 @@
import _ from 'lodash'; const _ = require('lodash');
import dedent from 'dedent'; const dedent = require('dedent-tabs').default;
const features = [ const features = [
'Astrological Botany', 'Biochemical Sorcery', 'Civil Divination', 'Astrological Botany', 'Biochemical Sorcery', 'Civil Divination',
@@ -18,7 +18,7 @@ const classnames = [
'Haberdasher', 'Manicurist', 'Netrunner', 'Weirkeeper' 'Haberdasher', 'Manicurist', 'Netrunner', 'Weirkeeper'
]; ];
export default { module.exports = {
non : function(snippetClasses){ non : function(snippetClasses){
return dedent` return dedent`
{{${snippetClasses} {{${snippetClasses}

View File

@@ -1,5 +1,5 @@
import _ from 'lodash'; const _ = require('lodash');
import dedent from 'dedent'; const dedent = require('dedent-tabs').default;
const titles = [ const titles = [
'The Burning Gallows', 'The Ring of Nenlast', 'The Burning Gallows', 'The Ring of Nenlast',
@@ -78,7 +78,7 @@ const coverText = [
'Enter a world of wonder and danger, where you can find allies and enemies among the various races and factions that inhabit it. You can choose to join or oppose any of them, or forge your own path. The game world is alive and responsive to your actions.' 'Enter a world of wonder and danger, where you can find allies and enemies among the various races and factions that inhabit it. You can choose to join or oppose any of them, or forge your own path. The game world is alive and responsive to your actions.'
]; ];
export default { module.exports = {
front : function() { front : function() {
return dedent` return dedent`

View File

@@ -1,9 +1,10 @@
import _ from 'lodash'; const _ = require('lodash');
import ClassFeatureGen from './classfeature.gen.js'; const ClassFeatureGen = require('./classfeature.gen.js');
import ClassTableGen from './classtable.gen.js';
export default function(){ const ClassTableGen = require('./classtable.gen.js');
module.exports = function(){
const classname = _.sample(['Archivist', 'Fancyman', 'Linguist', 'Fletcher', const classname = _.sample(['Archivist', 'Fancyman', 'Linguist', 'Fletcher',
'Notary', 'Berserker-Typist', 'Fishmongerer', 'Manicurist', 'Haberdasher', 'Concierge']); 'Notary', 'Berserker-Typist', 'Fishmongerer', 'Manicurist', 'Haberdasher', 'Concierge']);

View File

@@ -1,4 +1,4 @@
import _ from 'lodash'; const _ = require('lodash');
const spellNames = [ const spellNames = [
'Astral Rite of Acne', 'Astral Rite of Acne',
@@ -54,7 +54,7 @@ const itemNames = [
'Staff of Endless Confetti', 'Staff of Endless Confetti',
]; ];
export default { module.exports = {
spellList : function(){ spellList : function(){
const levels = ['Cantrips (0 Level)', '1st Level', '2nd Level', '3rd Level', '4th Level', '5th Level', '6th Level', '7th Level', '8th Level', '9th Level']; const levels = ['Cantrips (0 Level)', '1st Level', '2nd Level', '3rd Level', '4th Level', '5th Level', '6th Level', '7th Level', '8th Level', '9th Level'];

View File

@@ -1,5 +1,5 @@
import _ from 'lodash'; const _ = require('lodash');
import dedent from 'dedent'; const dedent = require('dedent-tabs').default;
const genList = function(list, max){ const genList = function(list, max){
return _.sampleSize(list, _.random(0, max)).join(', ') || 'None'; return _.sampleSize(list, _.random(0, max)).join(', ') || 'None';
@@ -152,7 +152,7 @@ const genAction = function(){
}; };
export default { module.exports = {
monster : function(classes, genLines){ monster : function(classes, genLines){
return dedent` return dedent`

View File

@@ -1,4 +1,4 @@
import _ from 'lodash'; const _ = require('lodash');
const quotes = [ const quotes = [
'The sword glinted in the dim light, its edges keen and deadly. As the adventurer reached for it, he couldn\'t help but feel a surge of excitement mixed with fear. This was no ordinary blade.', 'The sword glinted in the dim light, its edges keen and deadly. As the adventurer reached for it, he couldn\'t help but feel a surge of excitement mixed with fear. This was no ordinary blade.',
@@ -40,7 +40,7 @@ const books = [
'Frost and Fury', 'Frost and Fury',
]; ];
export default ()=>{ module.exports = ()=>{
return ` return `
{{quote {{quote
${_.sample(quotes)} ${_.sample(quotes)}

View File

@@ -1,7 +1,7 @@
import _ from 'lodash'; const _ = require('lodash');
import dedent from 'dedent'; const dedent = require('dedent-tabs').default;
export default { module.exports = {
dwarvish : ()=>{ dwarvish : ()=>{
return dedent `##### Dwarvish Runes: Sample Alphabet return dedent `##### Dwarvish Runes: Sample Alphabet
{{runeTable,wide,frame,font-family:Davek {{runeTable,wide,frame,font-family:Davek

View File

@@ -1,5 +1,5 @@
import _ from 'lodash'; const _ = require('lodash');
export default ()=>{ module.exports = ()=>{
return `{{watercolor${_.random(1, 12)},top:20px,left:30px,width:300px,background-color:#BBAD82,opacity:80%}}\n\n`; return `{{watercolor${_.random(1, 12)},top:20px,left:30px,width:300px,background-color:#BBAD82,opacity:80%}}\n\n`;
}; };

View File

@@ -615,7 +615,6 @@
text-align : center; text-align : center;
-webkit-text-stroke : 0.1cm black; -webkit-text-stroke : 0.1cm black;
paint-order : stroke; paint-order : stroke;
text-transform : none;
} }
.logo { .logo {
position : absolute; position : absolute;

View File

@@ -1,18 +1,19 @@
/* eslint-disable max-lines */ /* eslint-disable max-lines */
import dedent from 'dedent';
import WatercolorGen from './snippets/watercolor.gen.js';
import ImageMaskGen from './snippets/imageMask.gen.js';
import FooterGen from './snippets/footer.gen.js';
import LicenseGenWotC from './snippets/licenseWotC.gen.js';
import LicenseGenGNU from './snippets/licenseGNU.gen.js';
import LicenseGen from './snippets/license.gen.js';
import LicenseGenAelf from './snippets/licenseAELF.js';
import LicenseDTTRPGGCC from './snippets/licenseDTRPGCC.gen.js';
import LicenseMongoosePublishing from './snippets/licenseMongoose.gen.js';
import TableOfContentsGen from './snippets/tableOfContents.gen.js';
import indexGen from './snippets/index.gen.js';
export default [ const WatercolorGen = require('./snippets/watercolor.gen.js');
const ImageMaskGen = require('./snippets/imageMask.gen.js');
const FooterGen = require('./snippets/footer.gen.js');
const LicenseGenWotC = require('./snippets/licenseWotC.gen.js');
const LicenseGenGNU = require('./snippets/licenseGNU.gen.js');
const LicenseGen = require('./snippets/license.gen.js');
const LicenseGenAelf = require('./snippets/licenseAELF.js');
const LicenseDTTRPGGCC = require('./snippets/licenseDTRPGCC.gen.js');
const LicenseMongoosePublishing = require('./snippets/licenseMongoose.gen.js');
const dedent = require('dedent-tabs').default;
const TableOfContentsGen = require('./snippets/tableOfContents.gen.js');
const indexGen = require('./snippets/index.gen.js');
module.exports = [
{ {
groupName : 'Text Editor', groupName : 'Text Editor',
@@ -208,7 +209,7 @@ export default [
view : 'text', view : 'text',
snippets : [ snippets : [
{ {
name : 'AELF', name : 'AELF',
subsnippets : [ subsnippets : [
{ {
name : 'Title Page Declaration', name : 'Title Page Declaration',
@@ -328,51 +329,51 @@ export default [
] ]
}, },
{ {
name : 'DTRPG Community Content', name : 'DTRPG Community Content',
incon : 'fab fa-dtrpg', incon : 'fab fa-dtrpg',
subsnippets : [ subsnippets : [
{ {
name : 'Chronicle System Guild Colophon', name : "Chronicle System Guild Colophon",
gen : LicenseDTTRPGGCC.greenRoninChronicleSystemGuildColophon, gen : LicenseDTTRPGGCC.greenRoninChronicleSystemGuildColophon,
}, },
{ {
name : 'Green Ronin\'s Age Creator\'s Alliance', name : 'Green Ronin\'s Age Creator\'s Alliance',
subsnippets : [ subsnippets : [
{ {
name : 'Required Text', name : "Required Text",
subsnippets : [ subsnippets : [
{ {
name : 'Colophon', name : "Colophon",
gen : LicenseDTTRPGGCC.greenRoninAgeCreatorsAllianceColophon, gen : LicenseDTTRPGGCC.greenRoninAgeCreatorsAllianceColophon,
}, },
{ {
name : 'Cover', name : "Cover",
gen : LicenseDTTRPGGCC.greenRoninAgeCreatorsAllianceCover, gen : LicenseDTTRPGGCC.greenRoninAgeCreatorsAllianceCover,
}, },
] ]
}, },
{ {
name : 'Logos', name : "Logos",
subsnippets : [ subsnippets : [
{ {
name : 'Age', name : "Age",
gen : LicenseDTTRPGGCC.greenRoninAgeCreatorsAllianceLogo, gen : LicenseDTTRPGGCC.greenRoninAgeCreatorsAllianceLogo,
}, },
{ {
name : 'Blue Rose', name : "Blue Rose",
gen : LicenseDTTRPGGCC.greenRoninAgeCreatorsAllianceBlueRoseLogo, gen : LicenseDTTRPGGCC.greenRoninAgeCreatorsAllianceBlueRoseLogo,
}, },
{ {
name : 'Fantasy Age Compatible', name : "Fantasy Age Compatible",
gen : LicenseDTTRPGGCC.greenRoninAgeCreatorsAllianceFantasyAgeCompatible, gen : LicenseDTTRPGGCC.greenRoninAgeCreatorsAllianceFantasyAgeCompatible,
}, },
{ {
name : 'Modern AGE Compatible', name : "Modern AGE Compatible",
gen : LicenseDTTRPGGCC.greenRoninAgeCreatorsAllianceModernAGECompatible, gen : LicenseDTTRPGGCC.greenRoninAgeCreatorsAllianceModernAGECompatible,
}, },
] ]
@@ -381,30 +382,30 @@ export default [
}, },
{ {
name : 'Hero Kid\'s Creators Guild', name : "Hero Kid\'s Creators Guild",
subsnippets : [ subsnippets : [
{ {
name : 'Required Text', name: "Required Text",
subsnippets : [ subsnippets : [
{ {
name : 'heroForgeHeroKidsCreatorsGuildColophon', name : "heroForgeHeroKidsCreatorsGuildColophon",
gen : LicenseDTTRPGGCC.heroForgeHeroKidsCreatorsGuildColophon, gen : LicenseDTTRPGGCC.heroForgeHeroKidsCreatorsGuildColophon,
}, },
{ {
name : 'heroForgeHeroKidsCreatorsGuildSuperKidsColophon', name : "heroForgeHeroKidsCreatorsGuildSuperKidsColophon",
gen : LicenseDTTRPGGCC.heroForgeHeroKidsCreatorsGuildSuperKidsColophon, gen : LicenseDTTRPGGCC.heroForgeHeroKidsCreatorsGuildSuperKidsColophon,
}, },
{ {
name : 'heroForgeHeroKidsCreatorsGuildCover', name : "heroForgeHeroKidsCreatorsGuildCover",
gen : LicenseDTTRPGGCC.heroForgeHeroKidsCreatorsGuildCover, gen : LicenseDTTRPGGCC.heroForgeHeroKidsCreatorsGuildCover,
}, },
{ {
name : 'heroForgeHeroKidsCreatorsGuildSuperKidsCover', name : "heroForgeHeroKidsCreatorsGuildSuperKidsCover",
gen : LicenseDTTRPGGCC.heroForgeHeroKidsCreatorsGuildSuperKidsCover, gen : LicenseDTTRPGGCC.heroForgeHeroKidsCreatorsGuildSuperKidsCover,
}, },
] ]
@@ -413,33 +414,33 @@ export default [
}, },
{ {
name : 'Travellers\' Aid Society', name : "Travellers' Aid Society",
subsnippets : [ subsnippets : [
{ {
name : 'Legal Statement', name : "Legal Statement",
gen : LicenseMongoosePublishing.TASLegal, gen : LicenseMongoosePublishing.TASLegal,
} }
] ]
}, },
{ {
name : 'Super-Powered by M&M', name : "Super-Powered by M&M",
subsnippets : [ subsnippets : [
{ {
name : 'Required Text', name : "Required Text",
subsnippets : [ subsnippets : [
{ {
name : 'Colophon', name : "Colophon",
gen : LicenseDTTRPGGCC.greenRoninSuperPoweredMMColophon, gen : LicenseDTTRPGGCC.greenRoninSuperPoweredMMColophon,
}, },
{ {
name : 'Cover', name : "Cover",
gen : LicenseDTTRPGGCC.greenRoninSuperPoweredMMCover, gen : LicenseDTTRPGGCC.greenRoninSuperPoweredMMCover,
}, },
{ {
name : 'Section 15', name : "Section 15",
gen : LicenseDTTRPGGCC.greenRoninSuperPoweredMMSection15, gen : LicenseDTTRPGGCC.greenRoninSuperPoweredMMSection15,
}, },
] ]

View File

@@ -1,6 +1,6 @@
import Markdown from '../../../../shared/markdown.js'; import Markdown from '../../../../shared/markdown.js';
export default { module.exports = {
createFooterFunc : function(headerSize=1){ createFooterFunc : function(headerSize=1){
return (props)=>{ return (props)=>{
const cursorPos = props.cursorPos; const cursorPos = props.cursorPos;

View File

@@ -1,7 +1,7 @@
import _ from 'lodash'; const _ = require('lodash');
import dedent from 'dedent'; const dedent = require('dedent-tabs').default;
export default { module.exports = {
center : ()=>{ center : ()=>{
return dedent` return dedent`
{{imageMaskCenter${_.random(1, 16)},--offsetX:0%,--offsetY:0%,--rotation:0 {{imageMaskCenter${_.random(1, 16)},--offsetX:0%,--offsetY:0%,--rotation:0

View File

@@ -1,6 +1,6 @@
import dedent from 'dedent'; const dedent = require('dedent-tabs').default;
export default ()=>{ module.exports = ()=>{
return dedent` return dedent`
{{index,wide,columns:5; {{index,wide,columns:5;
##### Index ##### Index

View File

@@ -1,11 +1,11 @@
/* eslint-disable max-lines */
import dedent from 'dedent'; const dedent = require('dedent');
// Small and one-off licenses // Small and one-off licenses
// Licenses in this file consist of one or two functions at most. If something is larger, // Licenses in this file consist of one or two functions at most. If something is larger,
// has more assets, or variations, break it out into a distinct file. // has more assets, or variations, break it out into a distinct file.
export default { module.exports = {
mit : function () { mit : function () {
return dedent` return dedent`
@@ -35,28 +35,28 @@ export default {
}} }}
`; `;
}, },
cczero : `<i class="far fa-copyright"></i> \<year\> This work is openly licensed via [CC0](https://creativecommons.org/publicdomain/zero/1.0/)\n\n`, cczero : `<i class="far fa-copyright"></i> \<year\> This work is openly licensed via [CC0](https://creativecommons.org/publicdomain/zero/1.0/)\n\n`,
ccby : `<i class="far fa-copyright"></i> \<year\> This work is openly licensed via [CC BY 4.0](https://creativecommons.org/publicdomain/by/4.0/)\n\n`, ccby : `<i class="far fa-copyright"></i> \<year\> This work is openly licensed via [CC BY 4.0](https://creativecommons.org/publicdomain/by/4.0/)\n\n`,
ccbysa : `<i class="far fa-copyright"></i> \<year\> This work is openly licensed via [CC BY-SA 4.0](https://creativecommons.org/publicdomain/by-sa/4.0/)\n\n`, ccbysa : `<i class="far fa-copyright"></i> \<year\> This work is openly licensed via [CC BY-SA 4.0](https://creativecommons.org/publicdomain/by-sa/4.0/)\n\n`,
ccbync : `<i class="far fa-copyright"></i> \<year\> This work is openly licensed via [CC BY-NC 4.0](https://creativecommons.org/publicdomain/by-nc/4.0/)\n\n`, ccbync : `<i class="far fa-copyright"></i> \<year\> This work is openly licensed via [CC BY-NC 4.0](https://creativecommons.org/publicdomain/by-nc/4.0/)\n\n`,
ccbyncsa : `<i class="far fa-copyright"></i> \<year\> This work is openly licensed via [CC BY-NC-SA](https://creativecommons.org/publicdomain/by-nc-sa/4.0/)\n\n`, ccbyncsa : `<i class="far fa-copyright"></i> \<year\> This work is openly licensed via [CC BY-NC-SA](https://creativecommons.org/publicdomain/by-nc-sa/4.0/)\n\n`,
ccbynd : `<i class="far fa-copyright"></i> \<year\> This work is openly licensed via [CC BY-ND 4.0](https://creativecommons.org/publicdomain/by-nd/4.0/)\n\n`, ccbynd : `<i class="far fa-copyright"></i> \<year\> This work is openly licensed via [CC BY-ND 4.0](https://creativecommons.org/publicdomain/by-nd/4.0/)\n\n`,
ccbyncnd : `<i class="far fa-copyright"></i> \<year\> This work is openly licensed via [CC NY-NC-ND 4.0](https://creativecommons.org/publicdomain/by-nc-nd/4.0/)\n\n`, ccbyncnd : `<i class="far fa-copyright"></i> \<year\> This work is openly licensed via [CC NY-NC-ND 4.0](https://creativecommons.org/publicdomain/by-nc-nd/4.0/)\n\n`,
cczeroBadge : `![CC0](http://mirrors.creativecommons.org/presskit/buttons/88x31/svg/cc-zero.svg)`, cczeroBadge : `![CC0](http://mirrors.creativecommons.org/presskit/buttons/88x31/svg/cc-zero.svg)`,
ccbyBadge : `![CC BY](https://mirrors.creativecommons.org/presskit/buttons/88x31/svg/by.svg)`, ccbyBadge : `![CC BY](https://mirrors.creativecommons.org/presskit/buttons/88x31/svg/by.svg)`,
ccbysaBadge : `![CC BY-SA](https://mirrors.creativecommons.org/presskit/buttons/88x31/svg/by-sa.svg)`, ccbysaBadge : `![CC BY-SA](https://mirrors.creativecommons.org/presskit/buttons/88x31/svg/by-sa.svg)`,
ccbyncBadge : `![CC BY-NC](https://mirrors.creativecommons.org/presskit/buttons/88x31/svg/by-nc.svg)`, ccbyncBadge : `![CC BY-NC](https://mirrors.creativecommons.org/presskit/buttons/88x31/svg/by-nc.svg)`,
ccbyncsaBadge : `![CC BY-NC-SA](https://mirrors.creativecommons.org/presskit/buttons/88x31/svg/by-nc-sa.svg)`, ccbyncsaBadge : `![CC BY-NC-SA](https://mirrors.creativecommons.org/presskit/buttons/88x31/svg/by-nc-sa.svg)`,
ccbyndBadge : `![CC BY-ND](https://mirrors.creativecommons.org/presskit/buttons/88x31/svg/by-nd.svg)`, ccbyndBadge : `![CC BY-ND](https://mirrors.creativecommons.org/presskit/buttons/88x31/svg/by-nd.svg)`,
ccbyncndBadge : `![CC BY-NC-ND](https://mirrors.creativecommons.org/presskit/buttons/88x31/svg/by-nc-nd.svg)`, ccbyncndBadge : `![CC BY-NC-ND](https://mirrors.creativecommons.org/presskit/buttons/88x31/svg/by-nc-nd.svg)`,
shadowDarkNotice : `\[Product Name]\ is an independent product published under the Shadowdark RPG Third-Party License and is not affiliated with The Arcane Library, LLC. Shadowdark RPG © 2023 The Arcane Library, LLC.\n`, shadowDarkNotice : `\[Product Name]\ is an independent product published under the Shadowdark RPG Third-Party License and is not affiliated with The Arcane Library, LLC. Shadowdark RPG © 2023 The Arcane Library, LLC.\n`,
shadowDarkBlack : `![Shadowdark Black Logo](/assets/license_logos/The-Arcane-Library_Third-Party-License_Black.png){width:200px}`, shadowDarkBlack : `![Shadowdark Black Logo](/assets/license_logos/The-Arcane-Library_Third-Party-License_Black.png){width:200px}`,
shadowDarkWhite : `![Shadowdark White Logo](/assets/license_logos/The-Arcane-Library_Third-Party-License_White.png){width:200px}`, shadowDarkWhite : `![Shadowdark White Logo](/assets/license_logos/The-Arcane-Library_Third-Party-License_White.png){width:200px}`,
bladesDarkNotice : `This work is based on Blades in the Dark \(found at (http://www.bladesinthedark.com/)\), product of One Seven Design, developed and authored by John Harper, and licensed for our use under the Creative Commons Attribution 3.0 Unported license \(http://creativecommons.org/licenses/by/3.0/\).\n`, bladesDarkNotice : `This work is based on Blades in the Dark \(found at (http://www.bladesinthedark.com/)\), product of One Seven Design, developed and authored by John Harper, and licensed for our use under the Creative Commons Attribution 3.0 Unported license \(http://creativecommons.org/licenses/by/3.0/\).\n`,
bladesDarkLogo : `![Forged in the Dark](/assets/license_logos/Evil-Hat_Forged-In-The-Dark_Logo-V2.png)`, bladesDarkLogo : `![Forged in the Dark](/assets/license_logos/Evil-Hat_Forged-In-The-Dark_Logo-V2.png)`,
bladesDarkLogoAttribution : `*Blades in the Dark^tm^ is a trademark of One Seven Design. The Forged in the Dark Logo is © One Seven Design, and is used with permission.*`, bladesDarkLogoAttribution : `*Blades in the Dark^tm^ is a trademark of One Seven Design. The Forged in the Dark Logo is © One Seven Design, and is used with permission.*`,
iconsCompatibility : 'Compatibility with Icons requires Icons Superpowered Roleplaying from Ad Infinitum Adventures. Ad Infinitum Adventures does not guarantee compatibility, and does not endorse this product.', iconsCompatibility : 'Compatibility with Icons requires Icons Superpowered Roleplaying from Ad Infinitum Adventures. Ad Infinitum Adventures does not guarantee compatibility, and does not endorse this product.',
iconsTrademark : 'Icons Superpowered Roleplaying is a trademark of Steve Kenson, published exclusively by Ad Infinitum Adventures. The Icons Superpowered Roleplaying Compatibility Logo is a trademark of Ad Infinitum Adventures and is used under the Icons Superpowered Roleplaying Compatibility License.', iconsTrademark : 'Icons Superpowered Roleplaying is a trademark of Steve Kenson, published exclusively by Ad Infinitum Adventures. The Icons Superpowered Roleplaying Compatibility Logo is a trademark of Ad Infinitum Adventures and is used under the Icons Superpowered Roleplaying Compatibility License.',
icondsSection15 : 'Open Game License v 1.0, Copyright 2000, Wizards of the Coast, Inc.\n::\nFudge System Reference Document, Copyright 2005, Grey Ghost Press, Inc.; Authors Steffan O\Sullivan and Ann Dupuis, with additional material by Peter Bonney, DeirdRe Brooks, Reimer Behrends, Shawn Garbett, Steven Hammond, Ed Heil, Bernard Hsiung, Sedge Lewis, Gordon McCormick, Kent Matthewson, Peter Mikelsons, Anthony Roberson, Andy Skinner, Stephan Szabo, John Ughrin, Dmitri Zagidulin\n::\nFATE (Fantastic Adventures in Tabletop Entertainment), Copyright 2003 by Evil Hat Productions LLC; Authors Robert Donoghue and Fred Hicks\n::\nSpirit of the Century, Copyright 2006, Evil Hat Productions LLC. Authors Robert Donoghue, Fred Hicks, and Leonard Balsera.\n::\nIcons, Copyright 2010, Ad Infinitum Adventures; Author Steve Kenson.\n', icondsSection15 : 'Open Game License v 1.0, Copyright 2000, Wizards of the Coast, Inc.\n::\nFudge System Reference Document, Copyright 2005, Grey Ghost Press, Inc.; Authors Steffan O\Sullivan and Ann Dupuis, with additional material by Peter Bonney, DeirdRe Brooks, Reimer Behrends, Shawn Garbett, Steven Hammond, Ed Heil, Bernard Hsiung, Sedge Lewis, Gordon McCormick, Kent Matthewson, Peter Mikelsons, Anthony Roberson, Andy Skinner, Stephan Szabo, John Ughrin, Dmitri Zagidulin\n::\nFATE (Fantastic Adventures in Tabletop Entertainment), Copyright 2003 by Evil Hat Productions LLC; Authors Robert Donoghue and Fred Hicks\n::\nSpirit of the Century, Copyright 2006, Evil Hat Productions LLC. Authors Robert Donoghue, Fred Hicks, and Leonard Balsera.\n::\nIcons, Copyright 2010, Ad Infinitum Adventures; Author Steve Kenson.\n',
iconsCompatibilityLogo : '![Icons Compatibility Logo](/assets/license_logos/Ad-Infinitum-Adventures_Icons-Compatibility-License_Logo.png){width:200px}' iconsCompatibilityLogo : '![Icons Compatibility Logo](/assets/license_logos/Ad-Infinitum-Adventures_Icons-Compatibility-License_Logo.png){width:200px}'
}; };

View File

@@ -1,9 +1,9 @@
/* eslint-disable max-lines */
import dedent from 'dedent'; const dedent = require('dedent');
// AELF License // AELF License
export default { module.exports = {
aelfTitleNotice : function() { aelfTitleNotice : function() {
return `This work includes AELF Open Gaming Content, which may only be used under the terms of the AELF Open License version 1.0a. This product is not endorsed or reviewed by Mythmere Games LLC or any other contributor of AELF Open Gaming Content and does not represent the views of Mythmere Games LLC any other contributor.`; return `This work includes AELF Open Gaming Content, which may only be used under the terms of the AELF Open License version 1.0a. This product is not endorsed or reviewed by Mythmere Games LLC or any other contributor of AELF Open Gaming Content and does not represent the views of Mythmere Games LLC any other contributor.`;
}, },

View File

@@ -1,9 +1,9 @@
/* eslint-disable max-lines */
import dedent from 'dedent'; const dedent = require('dedent');
// DriveThruRPG/OneBookShelf Community Content Programs // DriveThruRPG/OneBookShelf Community Content Programs
export default { module.exports = {
// Alligator Alley Entertainment Starforger's Guild // Alligator Alley Entertainment Starforger's Guild
alligatorAlleyEntertainmentStarforgersGuildColophon : function() { alligatorAlleyEntertainmentStarforgersGuildColophon : function() {
return dedent ` return dedent `
@@ -168,8 +168,8 @@ export default {
`; `;
}, },
// Monte Cook's Cypher License // Monte Cook's Cypher License
monteCookCypherCover : `Requires the Cypher System Rulebook from Monte Cook Games. Distributed through the Cypher System CreatorTM at DriveThruRPG.`, monteCookCypherCover : `Requires the Cypher System Rulebook from Monte Cook Games. Distributed through the Cypher System CreatorTM at DriveThruRPG.`,
monteCookCypherColophon : function() { monteCookCypherColophon : function() {
return dedent` return dedent`
This product was created under license. CYPHER SYSTEM and its logo, and CYPHER SYSTEM CREATOR and its logo, are trademarks of Monte Cook Games, LLC in the U.S.A. and other countries. All Monte Cook Games characters and character names, and the distinctive likenesses thereof, are trademarks of Monte Cook Games, LLC. [](www.montecookgames.com) This product was created under license. CYPHER SYSTEM and its logo, and CYPHER SYSTEM CREATOR and its logo, are trademarks of Monte Cook Games, LLC in the U.S.A. and other countries. All Monte Cook Games characters and character names, and the distinctive likenesses thereof, are trademarks of Monte Cook Games, LLC. [](www.montecookgames.com)
@@ -179,10 +179,10 @@ export default {
`; `;
}, },
// Verify Logo redistribution // Verify Logo redistribution
monteCookLogoDarkLarge : `![Cypher System Compatible](/assets/license_logos/CSCDarkLarge.png)`, monteCookLogoDarkLarge : `![Cypher System Compatible](/assets/license_logos/CSCDarkLarge.png)`,
monteCookLogoDarkSmall : `![Cypher System Compatible](/assets/license_logos/CSCDarkSmall.png)`, monteCookLogoDarkSmall : `![Cypher System Compatible](/assets/license_logos/CSCDarkSmall.png)`,
monteCookLogoLightLarge : `![Cypher System Compatible](/assets/license_logos/CSCLightLarge.png)`, monteCookLogoLightLarge : `![Cypher System Compatible](/assets/license_logos/CSCLightLarge.png)`,
monteCookLogoLightSmall : `![Cypher System Compatible](/assets/license_logos/CSCLightSmall.png)`, monteCookLogoLightSmall : `![Cypher System Compatible](/assets/license_logos/CSCLightSmall.png)`,
// Onyx Path Canis Minor - Verify logos and access // Onyx Path Canis Minor - Verify logos and access
onyxPathCanisMinorColophon : function () { onyxPathCanisMinorColophon : function () {
return dedent` return dedent`

View File

@@ -1,9 +1,9 @@
/* eslint-disable max-lines */ /* eslint-disable max-lines */
import dedent from 'dedent'; const dedent = require('dedent');
// GNU Licenses // GNU Licenses
export default { module.exports = {
gpl3 : function () { gpl3 : function () {
return dedent`{{license,wide return dedent`{{license,wide

Some files were not shown because too many files have changed in this diff Show More