diff --git a/client/homebrew/pages/basePages/listPage/brewItem/brewItem.jsx b/client/homebrew/pages/basePages/listPage/brewItem/brewItem.jsx index 90f9d32f2..0369305d5 100644 --- a/client/homebrew/pages/basePages/listPage/brewItem/brewItem.jsx +++ b/client/homebrew/pages/basePages/listPage/brewItem/brewItem.jsx @@ -20,7 +20,8 @@ const BrewItem = createClass({ authors : [], stubbed : true }, - reportError : ()=>{} + updateListFilter : ()=>{}, + reportError : ()=>{} }; }, @@ -44,6 +45,10 @@ const BrewItem = createClass({ }); }, + updateFilter : function(type, term){ + this.props.updateListFilter(type, term); + }, + renderDeleteBrewLink : function(){ if(!this.props.brew.editId) return; @@ -109,6 +114,9 @@ const BrewItem = createClass({ const brew = this.props.brew; if(Array.isArray(brew.tags)) { // temporary fix until dud tags are cleaned brew.tags = brew.tags?.filter((tag)=>tag); //remove tags that are empty strings + brew.tags.sort((a, b)=>{ + return a.indexOf(':') - b.indexOf(':') != 0 ? a.indexOf(':') - b.indexOf(':') : a.toLowerCase().localeCompare(b.toLowerCase()); + }); } const dateFormatString = 'YYYY-MM-DD HH:mm:ss'; @@ -129,7 +137,7 @@ const BrewItem = createClass({ {brew.tags.map((tag, idx)=>{ const matches = tag.match(/^(?:([^:]+):)?([^:]+)$/); - return {matches[2]}; + return {this.updateFilter(tag);}}>{matches[2]}; })} : <> diff --git a/client/homebrew/pages/basePages/listPage/brewItem/brewItem.less b/client/homebrew/pages/basePages/listPage/brewItem/brewItem.less index 5a1bb3d92..9bee4e5eb 100644 --- a/client/homebrew/pages/basePages/listPage/brewItem/brewItem.less +++ b/client/homebrew/pages/basePages/listPage/brewItem/brewItem.less @@ -63,6 +63,41 @@ white-space: nowrap; display: inline-block; font-weight: bold; + border-color: currentColor; + cursor : pointer; + &:before { + font-family: 'Font Awesome 5 Free'; + font-size: 12px; + margin-right: 3px; + } + &.type { + background-color: #0080003b; + color: #008000; + &:before{ + content: '\f0ad'; + } + } + &.group { + background-color: #5050503b; + color: #000000; + &:before{ + content: '\f500'; + } + } + &.meta { + background-color: #0000803b; + color: #000080; + &:before{ + content: '\f05a'; + } + } + &.system { + background-color: #8000003b; + color: #800000; + &:before{ + content: '\f518'; + } + } } &:hover{ .links{ diff --git a/client/homebrew/pages/basePages/listPage/listPage.jsx b/client/homebrew/pages/basePages/listPage/listPage.jsx index d0cd11ec6..2385b4490 100644 --- a/client/homebrew/pages/basePages/listPage/listPage.jsx +++ b/client/homebrew/pages/basePages/listPage/listPage.jsx @@ -36,6 +36,7 @@ const ListPage = createClass({ return { filterString : this.props.query?.filter || '', + filterTags : [], sortType : this.props.query?.sort || null, sortDir : this.props.query?.dir || null, query : this.props.query, @@ -82,7 +83,7 @@ const ListPage = createClass({ if(!brews || !brews.length) return
No Brews.
; return _.map(brews, (brew, idx)=>{ - return ; + return { this.updateUrl(this.state.filterString, this.state.sortType, this.state.sortDir, tag); }}/>; }); }, @@ -136,13 +137,33 @@ const ListPage = createClass({ return; }, - updateUrl : function(filterTerm, sortType, sortDir){ + updateUrl : function(filterTerm, sortType, sortDir, filterTag=''){ const url = new URL(window.location.href); const urlParams = new URLSearchParams(url.search); urlParams.set('sort', sortType); urlParams.set('dir', sortDir); + let filterTags = urlParams.getAll('tag'); + if(filterTag != '') { + if(filterTags.findIndex((tag)=>{return tag.toLowerCase()==filterTag.toLowerCase();}) == -1){ + filterTags.push(filterTag); + } else { + filterTags = filterTags.filter((tag)=>{ return tag.toLowerCase() != filterTag.toLowerCase(); }); + } + } + urlParams.delete('tag'); + // Add tags to URL in the order they were clicked + filterTags.forEach((tag)=>{ urlParams.append('tag', tag); }); + // Sort tags before updating state + filterTags.sort((a, b)=>{ + return a.indexOf(':') - b.indexOf(':') != 0 ? a.indexOf(':') - b.indexOf(':') : a.toLowerCase().localeCompare(b.toLowerCase()); + }); + + this.setState({ + filterTags + }); + if(!filterTerm) urlParams.delete('filter'); else @@ -166,6 +187,16 @@ const ListPage = createClass({ ; }, + renderTagsOptions : function(){ + if(this.state.filterTags?.length == 0) return; + return
+ {_.map(this.state.filterTags, (tag, idx)=>{ + const matches = tag.match(/^(?:([^:]+):)?([^:]+)$/); + return { this.updateUrl(this.state.filterString, this.state.sortType, this.state.sortDir, tag); }}>{matches[2]}; + })} +
; + }, + renderSortOptions : function(){ return
Sort by :
@@ -176,9 +207,6 @@ const ListPage = createClass({ {/* {this.renderSortOption('Latest', 'latest')} */} {this.renderFilterOption()} - - -
; }, @@ -186,14 +214,28 @@ const ListPage = createClass({ const testString = _.deburr(this.state.filterString).toLowerCase(); brews = _.filter(brews, (brew)=>{ + // Filter by user entered text const brewStrings = _.deburr([ brew.title, brew.description, brew.tags].join('\n') .toLowerCase()); - return brewStrings.includes(testString); + const filterTextTest = brewStrings.includes(testString); + + // Filter by user selected tags + let filterTagTest = true; + if(this.state.filterTags.length > 0){ + filterTagTest = Array.isArray(brew.tags) && this.state.filterTags?.every((tag)=>{ + return brew.tags.findIndex((brewTag)=>{ + return brewTag.toLowerCase() == tag.toLowerCase(); + }) >= 0; + }); + } + + return filterTextTest && filterTagTest; }); + return _.orderBy(brews, (brew)=>{ return this.sortBrewOrder(brew); }, this.state.sortDir); }, @@ -224,6 +266,7 @@ const ListPage = createClass({ {this.props.navItems} {this.renderSortOptions()} + {this.renderTagsOptions()}
diff --git a/client/homebrew/pages/basePages/listPage/listPage.less b/client/homebrew/pages/basePages/listPage/listPage.less index 00d753429..0aa4a278d 100644 --- a/client/homebrew/pages/basePages/listPage/listPage.less +++ b/client/homebrew/pages/basePages/listPage/listPage.less @@ -53,7 +53,7 @@ } } } - .sort-container{ + .sort-container { font-family : 'Open Sans', sans-serif; position : sticky; top : 0; @@ -125,4 +125,66 @@ } + .tags-container { + height : 30px; + background-color : #555; + border-top : 1px solid #666; + border-bottom : 1px solid #666; + color : white; + display : flex; + justify-content : center; + align-items : center; + column-gap : 15px; + row-gap : 5px; + flex-wrap : wrap; + span { + font-family : 'Open Sans', sans-serif; + font-size : 11px; + font-weight : bold; + border : 1px solid; + border-radius : 3px; + padding : 3px; + cursor : pointer; + color: #dfdfdf; + &:before { + font-family: 'Font Awesome 5 Free'; + font-size: 12px; + margin-right: 3px; + } + &:after { + content: '\f00d'; + font-family: 'Font Awesome 5 Free'; + font-size: 12px; + margin-left: 3px; + } + &.type { + background-color: #008000; + border-color: #00a000; + &:before{ + content: '\f0ad'; + } + } + &.group { + background-color: #505050; + border-color: #000000; + &:before{ + content: '\f500'; + } + } + &.meta { + background-color: #000080; + border-color: #0000a0; + &:before{ + content: '\f05a'; + } + } + &.system { + background-color: #800000; + border-color: #a00000; + &:before{ + content: '\f518'; + } + } + } + } } diff --git a/client/homebrew/pages/homePage/welcome_msg.md b/client/homebrew/pages/homePage/welcome_msg.md index 9df769903..c7d46149e 100644 --- a/client/homebrew/pages/homePage/welcome_msg.md +++ b/client/homebrew/pages/homePage/welcome_msg.md @@ -143,6 +143,7 @@ Much nicer than `




` ### Column Breaks Column and page breaks with `\column` and `\page`. +\column ### Tables Tables now allow column & row spanning between cells. This is included in some updated snippets, but a simplified example is given below. diff --git a/package-lock.json b/package-lock.json index 770ff6716..9f39b3bd5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -48,7 +48,7 @@ "vitreum": "git+https://git@github.com/calculuschild/vitreum.git" }, "devDependencies": { - "eslint": "^8.56.0", + "eslint": "^8.57.0", "eslint-plugin-jest": "^27.9.0", "eslint-plugin-react": "^7.33.2", "jest": "^29.7.0", @@ -1958,9 +1958,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1978,13 +1978,13 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { @@ -2005,9 +2005,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, "node_modules/@istanbuljs/load-nyc-config": { @@ -5588,16 +5588,16 @@ } }, "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", diff --git a/package.json b/package.json index 884d293ec..b44d1cc4d 100644 --- a/package.json +++ b/package.json @@ -118,7 +118,7 @@ "vitreum": "git+https://git@github.com/calculuschild/vitreum.git" }, "devDependencies": { - "eslint": "^8.56.0", + "eslint": "^8.57.0", "eslint-plugin-jest": "^27.9.0", "eslint-plugin-react": "^7.33.2", "jest": "^29.7.0", diff --git a/themes/V3/5ePHB/style.less b/themes/V3/5ePHB/style.less index 23c3992fd..c155d1c09 100644 --- a/themes/V3/5ePHB/style.less +++ b/themes/V3/5ePHB/style.less @@ -307,7 +307,6 @@ margin-left : -0.16cm; background-color : var(--HB_Color_MonsterStatBackground); background-image : @monsterBlockBackground; - background-attachment : unset; background-blend-mode : overlay; border-style : solid; border-width : 7px 6px; diff --git a/themes/codeMirror/customThemes/darkvision.css b/themes/codeMirror/customThemes/darkvision.css new file mode 100644 index 000000000..4c74d105e --- /dev/null +++ b/themes/codeMirror/customThemes/darkvision.css @@ -0,0 +1,121 @@ +.CodeMirror { + background: #0C0C0C; + color: #B9BDB6; +} + +/* Brew BG */ +.brewRenderer { + background-color: #0C0C0C; +} + +.cm-s-darkvision { + /* Blinking cursor and selection */ + .CodeMirror-cursor { + border-left: 1px solid #B9BDB6; + } + .CodeMirror-selected { + background: #E0E8FF40; + } + + /* Line number stuff */ + .CodeMirror-gutter-elt { + color: #81969A; + } + .CodeMirror-linenumber { + background-color: #0C0C0C; + } + .CodeMirror-gutter { + background-color: #0C0C0C; + } + + /* column splits */ + .editor .codeEditor .columnSplit { + font-style: italic; + color: inherit; + background-color:#1F5763; + border-bottom: #299 solid 1px; + } + + /* # headings */ + .cm-header { + color: #C51B1B; + -webkit-text-stroke-width: 0.1px; + } + /* bold points */ + .cm-strong { + font-weight: bold; + color: #309DD2; + } + /* Link headings */ + .cm-link { + color: #DD6300; + } + /* links */ + .cm-string { + color: #5CE638; + } + /*@import*/ + .cm-def { + color: #2986CC; + } + /* Bullets and such */ + .cm-variable-2 { + color: #3CBF30; + } + + /* Tags (divs) */ + .cm-tag { + color: #E3FF00; + } + .cm-attribute { + color: #E3FF00; + } + .cm-atom { + color: #CF7EA9; + } + .cm-qualifier { + color: #EE1919; + } + .cm-comment { + color: #BBC700; + } + .cm-keyword { + color: #CC66FF; + } + .cm-property { + color: aqua; + } + .cm-error { + color: #C50202; + } + .CodeMirror-foldmarker { + color: #F0FF00; + } + /* New page */ + .cm-builtin { + color: #FFF; + } +} + +.editor .codeEditor { + /* blocks */ + .block:not(.cm-comment) { + color: magenta; + } + /* definition lists */ + .define.definition { + color: #FFAA3E; + } + .define.term { + color: #7290d9; + } + .define:not(.term):not(.definition) { + background: #333; + } + /* New page */ + .pageLine { + background: #000; + color: #000; + border-bottom: 1px solid #FFF; + } +} diff --git a/themes/codeMirror/editorThemes.json b/themes/codeMirror/editorThemes.json index 384ce4602..679c6874b 100644 --- a/themes/codeMirror/editorThemes.json +++ b/themes/codeMirror/editorThemes.json @@ -16,6 +16,7 @@ "colorforth", "darcula", "darkbrewery-v301", +"darkvision", "dracula", "duotone-dark", "duotone-light", diff --git a/themes/fonts/5e/dicefont.less b/themes/fonts/5e/dicefont.less new file mode 100644 index 000000000..887a7c27c --- /dev/null +++ b/themes/fonts/5e/dicefont.less @@ -0,0 +1,118 @@ +/* + Icon Font: dicefont +*/ +@font-face { + font-family: 'DiceFont'; + src: url('../../../fonts/5e/dicefont.woff2') format('woff2'), + url('../../../fonts/5e/dicefont.woff') format('woff'); + font-weight: normal; + font-style: normal; +} + +.df { + display: inline-block; + font-family: 'DiceFont'; + font-style: normal; + font-weight: normal; + font-variant: normal; + line-height: 1; + text-decoration: inherit; + text-rendering: optimizeLegibility; + text-transform: none; + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + font-smooth: antialiased; + &.F:before { content: '\f190'; } + &.F-minus:before { content: '\f191'; } + &.F-plus:before { content: '\f192'; } + &.F-zero:before { content: '\f193'; } + &.d10:before { content: '\f194'; } + &.d10-0:before { content: '\f100'; } + &.d10-1:before { content: '\f101'; } + &.d10-10:before { content: '\f102'; } + &.d10-2:before { content: '\f103'; } + &.d10-3:before { content: '\f104'; } + &.d10-4:before { content: '\f105'; } + &.d10-5:before { content: '\f106'; } + &.d10-6:before { content: '\f107'; } + &.d10-7:before { content: '\f108'; } + &.d10-8:before { content: '\f109'; } + &.d10-9:before { content: '\f10a'; } + &.d12:before { content: '\f195'; } + &.d12-1:before { content: '\f10b'; } + &.d12-10:before { content: '\f10c'; } + &.d12-11:before { content: '\f10d'; } + &.d12-12:before { content: '\f10e'; } + &.d12-2:before { content: '\f10f'; } + &.d12-3:before { content: '\f110'; } + &.d12-4:before { content: '\f111'; } + &.d12-5:before { content: '\f112'; } + &.d12-6:before { content: '\f113'; } + &.d12-7:before { content: '\f114'; } + &.d12-8:before { content: '\f115'; } + &.d12-9:before { content: '\f116'; } + &.d2:before { content: '\f196'; } + &.d2-1:before { content: '\f117'; } + &.d2-2:before { content: '\f118'; } + &.d20:before { content: '\f197'; } + &.d20-1:before { content: '\f119'; } + &.d20-10:before { content: '\f11a'; } + &.d20-11:before { content: '\f11b'; } + &.d20-12:before { content: '\f11c'; } + &.d20-13:before { content: '\f11d'; } + &.d20-14:before { content: '\f11e'; } + &.d20-15:before { content: '\f11f'; } + &.d20-16:before { content: '\f120'; } + &.d20-17:before { content: '\f121'; } + &.d20-18:before { content: '\f122'; } + &.d20-19:before { content: '\f123'; } + &.d20-2:before { content: '\f124'; } + &.d20-20:before { content: '\f125'; } + &.d20-3:before { content: '\f126'; } + &.d20-4:before { content: '\f127'; } + &.d20-5:before { content: '\f128'; } + &.d20-6:before { content: '\f129'; } + &.d20-7:before { content: '\f12a'; } + &.d20-8:before { content: '\f12b'; } + &.d20-9:before { content: '\f12c'; } + &.d4:before { content: '\f198'; } + &.d4-1:before { content: '\f12d'; } + &.d4-2:before { content: '\f12e'; } + &.d4-3:before { content: '\f12f'; } + &.d4-4:before { content: '\f130'; } + &.d6:before { content: '\f199'; } + &.d6-1:before { content: '\f131'; } + &.d6-2:before { content: '\f132'; } + &.d6-3:before { content: '\f133'; } + &.d6-4:before { content: '\f134'; } + &.d6-5:before { content: '\f135'; } + &.d6-6:before { content: '\f136'; } + &.d8:before { content: '\f19a'; } + &.d8-1:before { content: '\f137'; } + &.d8-2:before { content: '\f138'; } + &.d8-3:before { content: '\f139'; } + &.d8-4:before { content: '\f13a'; } + &.d8-5:before { content: '\f13b'; } + &.d8-6:before { content: '\f13c'; } + &.d8-7:before { content: '\f13d'; } + &.d8-8:before { content: '\f13e'; } + &.dot-d6:before { content: '\f19b'; } + &.dot-d6-1:before { content: '\f13f'; } + &.dot-d6-2:before { content: '\f140'; } + &.dot-d6-3:before { content: '\f141'; } + &.dot-d6-4:before { content: '\f142'; } + &.dot-d6-5:before { content: '\f143'; } + &.dot-d6-6:before { content: '\f18f'; } + &.small-dot-d6-1:before { content: '\f183'; } + &.small-dot-d6-2:before { content: '\f184'; } + &.small-dot-d6-3:before { content: '\f185'; } + &.small-dot-d6-4:before { content: '\f186'; } + &.small-dot-d6-5:before { content: '\f187'; } + &.small-dot-d6-6:before { content: '\f188'; } + &.solid-small-dot-d6-1:before { content: '\f189'; } + &.solid-small-dot-d6-2:before { content: '\f18a'; } + &.solid-small-dot-d6-3:before { content: '\f18b'; } + &.solid-small-dot-d6-4:before { content: '\f18c'; } + &.solid-small-dot-d6-5:before { content: '\f18d'; } + &.solid-small-dot-d6-6:before { content: '\f18e'; } +} \ No newline at end of file diff --git a/themes/fonts/5e/dicefont.woff b/themes/fonts/5e/dicefont.woff new file mode 100644 index 000000000..d6f54f38e Binary files /dev/null and b/themes/fonts/5e/dicefont.woff differ diff --git a/themes/fonts/5e/dicefont.woff2 b/themes/fonts/5e/dicefont.woff2 new file mode 100644 index 000000000..342bf7d95 Binary files /dev/null and b/themes/fonts/5e/dicefont.woff2 differ diff --git a/themes/fonts/5e/dicefont_license.md b/themes/fonts/5e/dicefont_license.md new file mode 100644 index 000000000..edfbd926d --- /dev/null +++ b/themes/fonts/5e/dicefont_license.md @@ -0,0 +1,18 @@ +# License + +DiceFont is open source. You can use it for commercial projects, personal +projects or open source projects. + +## Font License + +Applies to all desktop and webfont files: [License: SIL OFL 1.1](http://scripts.sil.org/OFL) + +## Code License + +Applies to all CSS and LESS files: [License: MIT License](http://opensource.org/licenses/mit-license.html) + +## Documentation License + +Applies to all other files [CC BY 3.0](http://creativecommons.org/licenses/by/3.0/) + +Copyright [Franco Ponticelli](https://github.com/fponticelli). diff --git a/themes/fonts/5e/fonts.less b/themes/fonts/5e/fonts.less index 8f089b51c..b59fe1671 100644 --- a/themes/fonts/5e/fonts.less +++ b/themes/fonts/5e/fonts.less @@ -1,3 +1,5 @@ +@import url('./dicefont.less'); + /* Main Font, serif */ @font-face { font-family: BookInsanityRemake;