diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index d43ae7c612..fb45afb28d 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -28,6 +28,7 @@ const Editor = createClass({ getDefaultProps : function() { return { brew : { +<<<<<<< HEAD text : '', style : '' }, @@ -37,6 +38,15 @@ const Editor = createClass({ onMetaChange : ()=>{}, renderer : 'legacy' +======= + text : '' + }, + onChange : ()=>{}, + + onMetadataChange : ()=>{}, + showMetaButton : true, + renderer : 'legacy' +>>>>>>> e3f9ef0 (v2.11.0 (#1265)) }; }, getInitialState : function() { @@ -68,6 +78,7 @@ const Editor = createClass({ }, handleInject : function(injectText){ +<<<<<<< HEAD const text = (this.isText() ? this.props.brew.text : this.props.brew.style); const lines = text.split('\n'); @@ -75,6 +86,10 @@ const Editor = createClass({ lines[cursorPos.line] = splice(lines[cursorPos.line], cursorPos.ch, injectText); this.refs.codeEditor.setCursorPosition(cursorPos.line + injectText.split('\n').length, cursorPos.ch + injectText.length); +======= + const lines = this.props.brew.text.split('\n'); + lines[this.cursorPosition.line] = splice(lines[this.cursorPosition.line], this.cursorPosition.ch, injectText); +>>>>>>> e3f9ef0 (v2.11.0 (#1265)) if(this.isText()) this.props.onTextChange(lines.join('\n')); if(this.isStyle()) this.props.onStyleChange(lines.join('\n')); @@ -99,9 +114,13 @@ const Editor = createClass({ if(this.state.view === 'text') { const codeMirror = this.refs.codeEditor.codeMirror; +<<<<<<< HEAD //reset custom text styles const customHighlights = codeMirror.getAllMarks(); for (let i=0;i{ +>>>>>>> e3f9ef0 (v2.11.0 (#1265)) const lineNumbers = _.reduce(this.props.brew.text.split('\n'), (r, line, lineNumber)=>{ @@ -117,6 +136,7 @@ const Editor = createClass({ } } +<<<<<<< HEAD // New Codemirror styling for V3 renderer if(this.props.renderer == 'V3') { if(line.startsWith('\\page')){ @@ -145,6 +165,27 @@ const Editor = createClass({ continue; } codeMirror.markText({ line: lineNumber, ch: match.index }, { line: lineNumber, ch: match.index + match[0].length }, { className: 'inline-block' }); +======= + if(line.match(/^\\column$/)){ + codeMirror.addLineClass(lineNumber, 'text', 'columnSplit'); + r.push(lineNumber); + } + + // Highlight inline spans {{content}} + if(line.includes('{{') && line.includes('}}')){ + const regex = /{{(?:="[\w,\-. ]*"|[^"'\s])*\s*|}}/g; + let match; + let blockCount = 0; + while ((match = regex.exec(line)) != null) { + if(match[0].startsWith('{')) { + blockCount += 1; + } else { + blockCount -= 1; + } + if(blockCount < 0) { + blockCount = 0; + continue; +>>>>>>> e3f9ef0 (v2.11.0 (#1265)) } } else if(line.trimLeft().startsWith('{{') || line.trimLeft().startsWith('}}')){ // Highlight block divs {{\n Content \n}} @@ -155,6 +196,14 @@ const Editor = createClass({ endCh = match.index+match[0].length; codeMirror.markText({ line: lineNumber, ch: 0 }, { line: lineNumber, ch: endCh }, { className: 'block' }); } + } else if(line.trimLeft().startsWith('{{') || line.trimLeft().startsWith('}}')){ + // Highlight block divs {{\n Content \n}} + let endCh = line.length+1; + + const match = line.match(/^ *{{(?:="[\w,\-. ]*"|[^"'\s])*$|^ *}}$/); + if(match) + endCh = match.index+match[0].length; + codeMirror.markText({ line: lineNumber, ch: 0 }, { line: lineNumber, ch: endCh }, { className: 'block' }); } return r; @@ -173,6 +222,7 @@ const Editor = createClass({ this.refs.codeEditor?.updateSize(); }, +<<<<<<< HEAD renderEditor : function(){ if(this.isText()){ return ; } +======= + renderMetadataEditor : function(){ + if(!this.state.showMetadataEditor) return; + return ; +>>>>>>> e3f9ef0 (v2.11.0 (#1265)) }, render : function(){ @@ -201,13 +259,33 @@ const Editor = createClass({
>>>>>> e3f9ef0 (v2.11.0 (#1265)) onInject={this.handleInject} showEditButtons={this.props.showEditButtons} renderer={this.props.renderer} /> +<<<<<<< HEAD {this.renderEditor()} +======= + {this.renderMetadataEditor()} + + + {/* +
+ +
+ */} +>>>>>>> e3f9ef0 (v2.11.0 (#1265))
); } diff --git a/client/homebrew/editor/snippetbar/snippetbar.jsx b/client/homebrew/editor/snippetbar/snippetbar.jsx index 9ea04695f5..d5ed32f4c3 100644 --- a/client/homebrew/editor/snippetbar/snippetbar.jsx +++ b/client/homebrew/editor/snippetbar/snippetbar.jsx @@ -16,6 +16,7 @@ const execute = function(val, brew){ const Snippetbar = createClass({ getDefaultProps : function() { return { +<<<<<<< HEAD brew : {}, view : 'text', onViewChange : ()=>{}, @@ -23,6 +24,14 @@ const Snippetbar = createClass({ onToggle : ()=>{}, showEditButtons : true, renderer : 'legacy' +======= + brew : {}, + onInject : ()=>{}, + onToggle : ()=>{}, + showmeta : false, + showMetaButton : true, + renderer : '' +>>>>>>> e3f9ef0 (v2.11.0 (#1265)) }; }, diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index dfb4908a0f..fefbd0f69d 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -24,9 +24,9 @@ const HomePage = createClass({ getDefaultProps : function() { return { brew : { - text : '', + text : '' }, - ver : '0.0.0' + ver : '0.0.0' }; }, getInitialState : function() { diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index e77fbc9877..6031dd521c 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -120,6 +120,12 @@ const NewPage = createClass({ localStorage.setItem(BREWKEY, text); }, + handleMetadataChange : function(metadata){ + this.setState({ + brew : _.merge({}, this.state.brew, metadata) + }); + }, + handleStyleChange : function(style){ this.setState((prevState)=>({ brew : _.merge({}, prevState.brew, { style: style }), diff --git a/client/homebrew/phbStyle/phb.style.less b/client/homebrew/phbStyle/phb.style.less new file mode 100644 index 0000000000..c4c38c5d1b --- /dev/null +++ b/client/homebrew/phbStyle/phb.style.less @@ -0,0 +1,515 @@ +@import (less) './client/homebrew/phbStyle/phb.fonts.css'; +@import (less) './client/homebrew/phbStyle/phb.assets.less'; + +//Colors +@background : #EEE5CE; +@noteGreen : #e0e5c1; +@headerUnderline : #c9ad6a; +@horizontalRule : #9c2b1b; +@headerText : #58180D; +@monsterStatBackground : #FDF1DC; +@page { margin: 0; } +body { + counter-reset : phb-page-numbers; +} +*{ + -webkit-print-color-adjust : exact; +} +.useSansSerif(){ + font-family : ScalySans; + font-size : 10pt; + em{ + font-style : italic; + } + strong{ + font-weight : 800; + letter-spacing : -0.02em; + } +} +.useColumns(@multiplier : 1){ + column-count : 2; + column-fill : auto; + column-gap : 1cm; + column-width : 8cm * @multiplier; + -webkit-column-count : 2; + -moz-column-count : 2; + -webkit-column-width : 8cm * @multiplier; + -moz-column-width : 8cm * @multiplier; + -webkit-column-gap : 1cm; + -moz-column-gap : 1cm; +} +.phb3{ + .useColumns(); + counter-increment : phb-page-numbers; + position : relative; + z-index : 15; + box-sizing : border-box; + overflow : hidden; + height : 279.4mm; + width : 215.9mm; + padding : 1.0cm 1.7cm 1.5cm; + background-color : @background; + background-image : @backgroundImage; + font-family : BookSanity; + font-size : 0.317cm; + text-rendering : optimizeLegibility; + page-break-before : always; + page-break-after : always; + //***************************** + // * BASE + // *****************************/ + p{ + overflow-wrap : break-word; + padding-top : 0em; + line-height : 1.3em; + &+p{ + padding-top : 0em; + } + } + ul{ + margin-bottom : 0.8em; + padding-left : 1.4em; + line-height : 1.3em; + list-style-position : outside; + list-style-type : disc; + } + ol{ + margin-bottom : 0.8em; + padding-left : 1.4em; + line-height : 1.3em; + list-style-position : outside; + list-style-type : decimal; + } + //Indents after p or lists + p+p, ul+p, ol+p{ + text-indent : 1em; + } + img{ + z-index : -1; + } + strong{ + font-weight : bold; + letter-spacing : 0.03em; + } + em{ + font-style : italic; + } + sup{ + vertical-align : super; + font-size : smaller; + line-height : 0; + } + sub{ + vertical-align : sub; + font-size : smaller; + line-height : 0; + } + //***************************** + // * HEADERS + // *****************************/ + h1,h2,h3,h4{ + margin-top : 0.2em; + margin-bottom : 0.2em; + font-family : MrJeeves; + font-weight : 800; + color : @headerText; + } + h1{ + column-span : all; + font-size : 0.987cm; + -webkit-column-span : all; + -moz-column-span : all; + &+p::first-letter{ + float : left; + font-family : Solberry; + line-height : 0.8em; + font-size: 3.1cm; + padding-top: 4px; + padding-bottom: 4px; + margin-top: -6px; + margin-left: -6px; + background-image: linear-gradient(-45deg, #322814, #998250, #322814); + background-clip: text; + -webkit-background-clip: text; + color: rgba(0, 0, 0, 0); + } + &+p::first-line{ + font-size : .385cm; + font-variant : small-caps; + } + } + h2{ + font-size : 0.705cm; + } + h3{ + font-size : 0.529cm; + border-bottom : 2px solid @headerUnderline; + } + h4{ + margin-bottom : 0.00em; + font-size : 0.458cm; + } + h5{ + margin-bottom : 0.2em; + font-family : ScalySansSmallCaps; + font-size : 0.423cm; + font-weight : 900; + } + //***************************** + // * TABLE + // *****************************/ + table{ + .useSansSerif(); + width : 100%; + margin-bottom : 1em; + font-size : 10pt; + thead{ + display: table-row-group; + font-weight : 800; + th{ + vertical-align : bottom; + padding-bottom : 0.3em; + padding-right : 0.1em; + padding-left : 0.1em; + } + } + tbody{ + tr{ + td{ + padding : 0.3em 0.1em; + } + &:nth-child(odd){ + background-color : @noteGreen; + } + } + } + } + //***************************** + // * NOTE + // *****************************/ + blockquote{ + .useSansSerif(); + box-sizing : border-box; + margin-bottom : 1em; + padding : 5px 10px; + background-color : @noteGreen; + border-style : solid; + border-width : 11px; + border-image : @noteBorderImage 11; + border-image-outset : 9px 0px; + box-shadow : 1px 4px 14px #888; + -webkit-transform : translateZ(0); //Prevents shadows from breaking across columns + p, ul{ + font-size : 0.352cm; + line-height : 1.1em; + } + } + //If a note starts a column, give it space at the top to render border + pre+blockquote, h2+blockquote, h3+blockquote, h4+blockquote, h5+blockquote { + margin-top : 13px; + } + //***************************** + // * MONSTER STAT BLOCK + // *****************************/ + hr+blockquote{ + position : relative; + padding-top : 15px; + background-color : @monsterStatBackground; + border-style : solid; + border-width : 10px; + border-image : @monsterBorderImage 10; + h2{ + margin-top : -8px; + margin-bottom : 0px; + &+p{ + padding-bottom : 0px; + } + } + h3{ + font-family : ScalySans; + font-weight : 400; + border-bottom : 1px solid @headerText; + } + hr+ul{ + color : @headerText; + } + ul{ + .useSansSerif(); + padding-left : 1em; + font-size : 0.352cm; + } + // Monster Ability table + hr+table{ + margin : 0; + column-span : 1; + background-color : transparent; + border-style : none; + border-image : none; + -webkit-column-span : 1; + tbody{ + tr:nth-child(odd), tr:nth-child(even){ + background-color : transparent; + } + } + } + table{ + color : @headerText; + } + p+p{ + margin-top : 0em; + padding-bottom : 0.5em; + text-indent : 0em; + } + //Triangle dividers + hr{ + visibility : visible; + height : 6px; + margin : 4px 0px; + background-image : @redTriangleImage; + background-size : 100% 100%; + border : none; + } + } + //Full Width + hr+hr+blockquote{ + .useColumns(0.96); + } + //***************************** + // * FOOTER + // *****************************/ + &:after{ + content : ""; + position : absolute; + bottom : 0px; + left : 0px; + z-index : 100; + height : 50px; + width : 100%; + background-image : @footerAccentImage; + background-size : cover; + } + &:nth-child(even){ + &:after{ + transform : scaleX(-1); + } + .pageNumber{ + left : 2px; + } + .footnote{ + left : 80px; + text-align : left; + } + } + .pageNumber{ + position : absolute; + right : 2px; + bottom : 22px; + width : 50px; + font-size : 0.9em; + color : #c9ad6a; + text-align : center; + &.auto::after { + content : counter(phb-page-numbers); + } + } + .footnote{ + position : absolute; + right : 80px; + bottom : 32px; + z-index : 150; + width : 200px; + font-size : 0.8em; + color : #c9ad6a; + text-align : right; + } + //***************************** + // * EXTRAS + // *****************************/ + hr{ + visibility : hidden; + margin : 0px; + } + //Modified unorder list, used in spells + hr+ul{ + margin-bottom : 0.5em; + padding-left : 1em; + text-indent : -1em; + list-style-type : none; + } + .columnSplit { + visibility : hidden; + -webkit-column-break-after : always; + break-after : always; + -moz-column-break-after : always; + break-before : column; + } + //Avoid breaking up + p,blockquote,table{ + z-index : 15; + -webkit-column-break-inside : avoid; + page-break-inside : avoid; + break-inside : avoid; + } + //Better spacing for spell blocks + h4+p+hr+ul{ + margin-top : -0.5em + } + //Text indent right after table + table+p{ + text-indent : 1em; + } + // Nested lists + ul ul,ol ol,ul ol,ol ul{ + margin-bottom : 0px; + margin-left : 1.5em; + } + li{ + -webkit-column-break-inside : avoid; + page-break-inside : avoid; + break-inside : avoid; + } +} +//***************************** +// * SPELL LIST +// *****************************/ +.phb3 .spellList{ + .useSansSerif(); + column-count : 4; + column-span : all; + -webkit-column-span : all; + -moz-column-span : all; + ul+h5{ + margin-top : 15px; + } + p, ul{ + font-size : 0.352cm; + line-height : 1.3em; + } + ul{ + margin-bottom : 0.5em; + padding-left : 1em; + text-indent : -1em; + list-style-type : none; + -webkit-column-break-inside : auto; + page-break-inside : auto; + break-inside : auto; + } +} +//***************************** +// * WIDE +// *****************************/ +.phb3 .wide{ + column-span : all; + -webkit-column-span : all; + -moz-column-span : all; +} +//***************************** +// * CLASS TABLE +// *****************************/ +.phb3 .classTable{ + margin-top : 25px; + margin-bottom : 40px; + border-collapse : separate; + background-color : white; + border : initial; + border-style : solid; + border-image-outset : 25px 17px; + border-image-repeat : stretch; + border-image-slice : 150 200 150 200; + border-image-source : @frameBorderImage; + border-image-width : 47px; + h5{ + margin-bottom : 10px; + } +} +//************************************ +// * DESCRIPTIVE TEXT BOX +// ************************************/ +.phb3 .descriptive{ + display : block-inline; + margin-bottom : 1em; + background-color : #faf7ea; + font-family : ScalySans; + border-style : solid; + border-width : 7px; + border-image : @descriptiveBoxImage 12 stretch; + border-image-outset : 4px; + box-shadow : 0px 0px 6px #faf7ea; + p{ + display : block; + padding-bottom : 0px; + line-height : 1.5em; + } + p + p { + padding-top : .8em; + } + em { + font-family : ScalySans; + font-style : italic; + } + strong { + font-family : ScalySans; + font-weight : 800; + letter-spacing : -0.02em; + } +} +.phb3 pre+.descriptive{ + margin-top : 8px; +} +//***************************** +// * TABLE OF CONTENTS +// *****************************/ +.phb3 .toc{ + -webkit-column-break-inside : avoid; + page-break-inside : avoid; + break-inside : avoid; + a{ + color : black; + text-decoration : none; + &:hover{ + text-decoration : underline; + } + } + ul{ + padding-left : 0; + list-style-type : none; + } + &>ul>li{ + margin-bottom : 10px; + } +} + +//***************************** +// * MUSTACHE DIVS/SPANS +// *****************************/ +.phb3 { + .inline-block { + display : block; + } +} + +//***************************** +// * DEFINITION LISTS +// *****************************/ +.phb3 { + // dl { + // margin-top: 10px; + // } + dt { + float: left; + //clear: left; //Doesn't seem necessary + margin-right: 5px; + } + // dd { + // margin-left: 0px; + // } +} + +//***************************** +// * BLANK LINE +// *****************************/ +.phb3 { + .blank { + height: 0.8em; + } +} diff --git a/shared/naturalcrit/codeEditor/codeEditor.jsx b/shared/naturalcrit/codeEditor/codeEditor.jsx index 9707bde560..3f07401936 100644 --- a/shared/naturalcrit/codeEditor/codeEditor.jsx +++ b/shared/naturalcrit/codeEditor/codeEditor.jsx @@ -96,6 +96,12 @@ const CodeEditor = createClass({ if(selection.length === 0){ const cursor = this.codeMirror.getCursor(); this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - 4 }); + }; + }, + + componentDidUpdate : function(prevProps) { + if(this.codeMirror && this.codeMirror.getValue() != this.props.value) { + this.codeMirror.setValue(this.props.value); } },