mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2025-12-24 20:42:43 +00:00
Merge branch 'master' into Issue_241
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
"stylelint-config-recess-order",
|
||||
"stylelint-config-recommended"],
|
||||
"plugins": [
|
||||
"stylelint-stylistic",
|
||||
"@stylistic/stylelint-plugin",
|
||||
"./stylelint_plugins/declaration-colon-align.js",
|
||||
"./stylelint_plugins/declaration-colon-min-space-before",
|
||||
"./stylelint_plugins/declaration-block-multi-line-min-declarations"
|
||||
@@ -16,32 +16,32 @@
|
||||
"font-family-no-missing-generic-family-keyword" : null,
|
||||
"font-weight-notation" : "named-where-possible",
|
||||
"font-family-name-quotes" : "always-unless-keyword",
|
||||
"stylistic/indentation" : "tab",
|
||||
"@stylistic/indentation" : "tab",
|
||||
"no-duplicate-selectors" : true,
|
||||
"stylistic/color-hex-case" : "upper",
|
||||
"@stylistic/color-hex-case" : "upper",
|
||||
"color-hex-length" : "long",
|
||||
"stylistic/selector-combinator-space-after" : "always",
|
||||
"stylistic/selector-combinator-space-before" : "always",
|
||||
"stylistic/selector-attribute-operator-space-before" : "never",
|
||||
"stylistic/selector-attribute-operator-space-after" : "never",
|
||||
"stylistic/selector-attribute-brackets-space-inside" : "never",
|
||||
"@stylistic/selector-combinator-space-after" : "always",
|
||||
"@stylistic/selector-combinator-space-before" : "always",
|
||||
"@stylistic/selector-attribute-operator-space-before" : "never",
|
||||
"@stylistic/selector-attribute-operator-space-after" : "never",
|
||||
"@stylistic/selector-attribute-brackets-space-inside" : "never",
|
||||
"selector-attribute-quotes" : "always",
|
||||
"selector-pseudo-element-colon-notation" : "double",
|
||||
"stylistic/selector-pseudo-class-parentheses-space-inside" : "never",
|
||||
"stylistic/block-opening-brace-space-before" : "always",
|
||||
"@stylistic/selector-pseudo-class-parentheses-space-inside" : "never",
|
||||
"@stylistic/block-opening-brace-space-before" : "always",
|
||||
"naturalcrit/declaration-colon-min-space-before" : 1,
|
||||
"stylistic/declaration-block-trailing-semicolon" : "always",
|
||||
"stylistic/declaration-colon-space-after" : "always",
|
||||
"stylistic/number-leading-zero" : "always",
|
||||
"@stylistic/declaration-block-trailing-semicolon" : "always",
|
||||
"@stylistic/declaration-colon-space-after" : "always",
|
||||
"@stylistic/number-leading-zero" : "always",
|
||||
"function-url-quotes" : ["always", { "except": ["empty"] }],
|
||||
"function-url-scheme-disallowed-list" : ["data","http"],
|
||||
"comment-whitespace-inside" : "always",
|
||||
"stylistic/string-quotes" : "single",
|
||||
"stylistic/media-feature-range-operator-space-before" : "always",
|
||||
"stylistic/media-feature-range-operator-space-after" : "always",
|
||||
"stylistic/media-feature-parentheses-space-inside" : "never",
|
||||
"stylistic/media-feature-colon-space-before" : "always",
|
||||
"stylistic/media-feature-colon-space-after" : "always",
|
||||
"@stylistic/string-quotes" : "single",
|
||||
"@stylistic/media-feature-range-operator-space-before" : "always",
|
||||
"@stylistic/media-feature-range-operator-space-after" : "always",
|
||||
"@stylistic/media-feature-parentheses-space-inside" : "never",
|
||||
"@stylistic/media-feature-colon-space-before" : "always",
|
||||
"@stylistic/media-feature-colon-space-after" : "always",
|
||||
"naturalcrit/declaration-colon-align" : true,
|
||||
"naturalcrit/declaration-block-multi-line-min-declarations": 1
|
||||
}
|
||||
|
||||
@@ -388,7 +388,7 @@ const Editor = createClass({
|
||||
view={this.state.view}
|
||||
value={this.props.brew.style ?? DEFAULT_STYLE_TEXT}
|
||||
onChange={this.props.onStyleChange}
|
||||
enableFolding={false}
|
||||
enableFolding={true}
|
||||
editorTheme={this.state.editorTheme}
|
||||
rerenderParent={this.rerenderParent} />
|
||||
</>;
|
||||
|
||||
@@ -28,6 +28,7 @@ const MetadataEditor = createClass({
|
||||
return {
|
||||
metadata : {
|
||||
editId : null,
|
||||
shareId : null,
|
||||
title : '',
|
||||
description : '',
|
||||
thumbnail : '',
|
||||
@@ -196,6 +197,7 @@ const MetadataEditor = createClass({
|
||||
|
||||
const listThemes = (renderer)=>{
|
||||
return _.map(_.values(mergedThemes[renderer]), (theme)=>{
|
||||
if(theme.path == this.props.metadata.shareId) return;
|
||||
const preview = theme.thumbnail || `/themes/${theme.renderer}/${theme.path}/dropdownPreview.png`;
|
||||
const texture = theme.thumbnail || `/themes/${theme.renderer}/${theme.path}/dropdownTexture.png`;
|
||||
return <div className='item' key={`${renderer}_${theme.name}`} onClick={()=>this.handleTheme(theme)} title={''}>
|
||||
|
||||
@@ -1,258 +1,239 @@
|
||||
@import 'naturalcrit/styles/colors.less';
|
||||
|
||||
.metadataEditor{
|
||||
.metadataEditor {
|
||||
position : absolute;
|
||||
z-index : 5;
|
||||
box-sizing : border-box;
|
||||
width : 100%;
|
||||
padding : 25px;
|
||||
background-color : #999;
|
||||
height : calc(100vh - 54px); // 54px is the height of the navbar + snippet bar. probably a better way to dynamic get this.
|
||||
padding : 25px;
|
||||
overflow-y : auto;
|
||||
background-color : #999999;
|
||||
|
||||
.sectionHead {
|
||||
font-weight: 1000;
|
||||
margin: 20px 0;
|
||||
margin : 20px 0;
|
||||
font-weight : 1000;
|
||||
|
||||
&:first-of-type {
|
||||
margin-top: 0;
|
||||
}
|
||||
&:first-of-type { margin-top : 0; }
|
||||
}
|
||||
|
||||
& > div {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
& > div { margin-bottom : 10px; }
|
||||
|
||||
.field-group {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
display : flex;
|
||||
flex-wrap : wrap;
|
||||
gap : 10px;
|
||||
width : 100%;
|
||||
}
|
||||
|
||||
.field-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 5 0 200px;
|
||||
gap: 10px;
|
||||
display : flex;
|
||||
flex : 5 0 200px;
|
||||
flex-direction : column;
|
||||
gap : 10px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.field{
|
||||
.field {
|
||||
position : relative;
|
||||
display : flex;
|
||||
flex-wrap : wrap;
|
||||
width : 100%;
|
||||
min-width : 200px;
|
||||
position : relative;
|
||||
&>label{
|
||||
& > label {
|
||||
width : 80px;
|
||||
font-size : 11px;
|
||||
font-weight : 800;
|
||||
line-height : 1.8em;
|
||||
text-transform : uppercase;
|
||||
}
|
||||
&>.value{
|
||||
& > .value {
|
||||
flex : 1 1 auto;
|
||||
width : 50px;
|
||||
&:invalid {
|
||||
background : #ffb9b9;
|
||||
}
|
||||
&:invalid { background : #FFB9B9; }
|
||||
}
|
||||
input[type='text'], textarea {
|
||||
border : 1px solid gray;
|
||||
&:focus {
|
||||
outline: 1px solid #444;
|
||||
}
|
||||
&:focus { outline : 1px solid #444444; }
|
||||
}
|
||||
&.thumbnail{
|
||||
&.thumbnail {
|
||||
height : 1.4em;
|
||||
label{
|
||||
line-height: 2.0em;
|
||||
label { line-height : 2.0em; }
|
||||
.value {
|
||||
overflow : hidden;
|
||||
text-overflow : ellipsis;
|
||||
}
|
||||
.value{
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
button{
|
||||
border: 1px solid #999;
|
||||
color: white;
|
||||
padding: 0px 5px;
|
||||
background-color: black;
|
||||
&:hover{
|
||||
background-color: #777;
|
||||
}
|
||||
button {
|
||||
padding : 0px 5px;
|
||||
color : white;
|
||||
background-color : black;
|
||||
border : 1px solid #999999;
|
||||
&:hover { background-color : #777777; }
|
||||
}
|
||||
}
|
||||
|
||||
&.description {
|
||||
flex: 1;
|
||||
flex : 1;
|
||||
textarea.value {
|
||||
resize : none;
|
||||
height : auto;
|
||||
font-family : 'Open Sans', sans-serif;
|
||||
font-size : 0.8em;
|
||||
resize : none;
|
||||
}
|
||||
}
|
||||
|
||||
&.language .language-dropdown {
|
||||
max-width : 150px;
|
||||
z-index : 200;
|
||||
max-width : 150px;
|
||||
}
|
||||
small {
|
||||
display : inline-block;
|
||||
font-size : 0.6em;
|
||||
font-style : italic;
|
||||
line-height : 1.4em;
|
||||
display : inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.thumbnail-preview {
|
||||
position: relative;
|
||||
justify-self: center;
|
||||
width: 80px;
|
||||
height: min-content;
|
||||
flex: 1 1;
|
||||
max-height: 115px;
|
||||
aspect-ratio: 1 / 1;
|
||||
object-fit: contain;
|
||||
background-color: #AAA;
|
||||
position : relative;
|
||||
flex : 1 1;
|
||||
justify-self : center;
|
||||
width : 80px;
|
||||
height : min-content;
|
||||
max-height : 115px;
|
||||
aspect-ratio : 1 / 1;
|
||||
object-fit : contain;
|
||||
background-color : #AAAAAA;
|
||||
}
|
||||
|
||||
.systems.field .value{
|
||||
label{
|
||||
vertical-align : middle;
|
||||
margin-right : 15px;
|
||||
cursor : pointer;
|
||||
font-size : 0.7em;
|
||||
font-weight : 800;
|
||||
user-select : none;
|
||||
white-space : nowrap;
|
||||
.systems.field .value {
|
||||
label {
|
||||
display : inline-flex;
|
||||
align-items : center;
|
||||
}
|
||||
a {
|
||||
font-size : 0.7em;
|
||||
font-weight : 800;
|
||||
display : inline-flex;
|
||||
}
|
||||
input{
|
||||
margin-right : 15px;
|
||||
font-size : 0.7em;
|
||||
font-weight : 800;
|
||||
white-space : nowrap;
|
||||
vertical-align : middle;
|
||||
cursor : pointer;
|
||||
user-select : none;
|
||||
}
|
||||
a {
|
||||
display : inline-flex;
|
||||
font-size : 0.7em;
|
||||
font-weight : 800;
|
||||
}
|
||||
input {
|
||||
margin : 3px;
|
||||
vertical-align : middle;
|
||||
cursor : pointer;
|
||||
}
|
||||
}
|
||||
.publish.field .value{
|
||||
position : relative;
|
||||
margin-bottom: 15px;
|
||||
button{
|
||||
width:100%;
|
||||
}
|
||||
button.publish{
|
||||
.publish.field .value {
|
||||
position : relative;
|
||||
margin-bottom : 15px;
|
||||
button { width : 100%; }
|
||||
button.publish {
|
||||
.button(@blueLight);
|
||||
}
|
||||
button.unpublish{
|
||||
button.unpublish {
|
||||
.button(@silver);
|
||||
}
|
||||
}
|
||||
|
||||
.delete.field .value{
|
||||
button{
|
||||
.delete.field .value {
|
||||
button {
|
||||
.button(@red);
|
||||
}
|
||||
}
|
||||
.authors.field .value{
|
||||
font-size: 0.8em;
|
||||
.authors.field .value {
|
||||
font-size : 0.8em;
|
||||
line-height : 1.5em;
|
||||
}
|
||||
|
||||
.themes.field{
|
||||
.themes.field {
|
||||
font-size : 13.33px;
|
||||
.navDropdownContainer {
|
||||
background-color : white;
|
||||
position : relative;
|
||||
z-index : 100;
|
||||
position : relative;
|
||||
z-index : 100;
|
||||
background-color : white;
|
||||
&.disabled {
|
||||
font-style :italic;
|
||||
font-style : italic;
|
||||
background-color : darkgray;
|
||||
color : dimgray;
|
||||
font-style : italic;
|
||||
color : dimgray;
|
||||
background-color : darkgray;
|
||||
}
|
||||
&>div:first-child {
|
||||
border : 2px solid rgb(118,118,118);
|
||||
padding : 6px 3px;
|
||||
background-color : inherit;
|
||||
i {
|
||||
float : right;
|
||||
}
|
||||
& > div:first-child {
|
||||
padding : 6px 3px;
|
||||
background-color : inherit;
|
||||
border : 2px solid rgb(118,118,118);
|
||||
i { float : right; }
|
||||
&:hover {
|
||||
background-color : @blue;
|
||||
color : white;
|
||||
color : white;
|
||||
background-color : @blue;
|
||||
}
|
||||
}
|
||||
.navDropdown .item > p {
|
||||
width: 45%;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
height: 1.1em;
|
||||
width : 45%;
|
||||
height : 1.1em;
|
||||
overflow : hidden;
|
||||
text-overflow : ellipsis;
|
||||
white-space : nowrap;
|
||||
}
|
||||
.navDropdown {
|
||||
box-shadow : 0px 5px 10px rgba(0, 0, 0, 0.3);
|
||||
position : absolute;
|
||||
width : 100%;
|
||||
box-shadow : 0px 5px 10px rgba(0, 0, 0, 0.3);
|
||||
.item {
|
||||
padding : 3px 3px;
|
||||
border-top : 1px solid rgb(118, 118, 118);
|
||||
position : relative;
|
||||
padding : 3px 3px;
|
||||
overflow : visible;
|
||||
background-color : white;
|
||||
background-color : white;
|
||||
border-top : 1px solid rgb(118, 118, 118);
|
||||
.preview {
|
||||
display : flex;
|
||||
flex-direction: column;
|
||||
background : #ccc;
|
||||
border-radius : 5px;
|
||||
box-shadow : 0 0 5px black;
|
||||
width : 200px;
|
||||
color :black;
|
||||
position : absolute;
|
||||
top : 0;
|
||||
right : 0;
|
||||
opacity : 0;
|
||||
transition : opacity 250ms ease;
|
||||
z-index : 1;
|
||||
overflow :hidden;
|
||||
position : absolute;
|
||||
top : 0;
|
||||
right : 0;
|
||||
z-index : 1;
|
||||
display : flex;
|
||||
flex-direction : column;
|
||||
width : 200px;
|
||||
overflow : hidden;
|
||||
color : black;
|
||||
background : #CCCCCC;
|
||||
border-radius : 5px;
|
||||
box-shadow : 0 0 5px black;
|
||||
opacity : 0;
|
||||
transition : opacity 250ms ease;
|
||||
h6 {
|
||||
font-weight : 900;
|
||||
padding-inline:1em;
|
||||
padding-block :.5em;
|
||||
border-bottom :2px solid hsl(0,0%,40%);
|
||||
padding-block : 0.5em;
|
||||
padding-inline : 1em;
|
||||
font-weight : 900;
|
||||
border-bottom : 2px solid hsl(0,0%,40%);
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color : @blue;
|
||||
color : white;
|
||||
}
|
||||
&:hover > .preview {
|
||||
opacity: 1;
|
||||
color : white;
|
||||
background-color : @blue;
|
||||
}
|
||||
&:hover > .preview { opacity : 1; }
|
||||
.texture-container {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
overflow: hidden;
|
||||
position : absolute;
|
||||
top : 0;
|
||||
left : 0;
|
||||
width : 100%;
|
||||
height : 100%;
|
||||
min-height : 100%;
|
||||
overflow : hidden;
|
||||
> img {
|
||||
mask-image : linear-gradient(90deg, transparent, black 20%);
|
||||
-webkit-mask-image : linear-gradient(90deg, transparent, black 20%);
|
||||
position : absolute;
|
||||
right : 0;
|
||||
top : 0px;
|
||||
width : 50%;
|
||||
position : absolute;
|
||||
top : 0px;
|
||||
right : 0;
|
||||
width : 50%;
|
||||
min-height : 100%;
|
||||
-webkit-mask-image : linear-gradient(90deg, transparent, black 20%);
|
||||
mask-image : linear-gradient(90deg, transparent, black 20%);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -260,84 +241,69 @@
|
||||
}
|
||||
}
|
||||
.field .list {
|
||||
display: flex;
|
||||
flex: 1 0;
|
||||
flex-wrap: wrap;
|
||||
display : flex;
|
||||
flex : 1 0;
|
||||
flex-wrap : wrap;
|
||||
|
||||
> * {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
> * { flex : 0 0 auto; }
|
||||
|
||||
#groupedIcon {
|
||||
#backgroundColors;
|
||||
display: inline-block;
|
||||
height: ~"calc(100% + 0.6em)";
|
||||
position: relative;
|
||||
top: -0.3em;
|
||||
right: -0.3em;
|
||||
cursor: pointer;
|
||||
min-width: 20px;
|
||||
text-align: center;
|
||||
color: white;
|
||||
position : relative;
|
||||
top : -0.3em;
|
||||
right : -0.3em;
|
||||
display : inline-block;
|
||||
min-width : 20px;
|
||||
height : ~'calc(100% + 0.6em)';
|
||||
color : white;
|
||||
text-align : center;
|
||||
cursor : pointer;
|
||||
|
||||
i {
|
||||
position: relative;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
position : relative;
|
||||
top : 50%;
|
||||
transform : translateY(-50%);
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
border-right: 1px solid black;
|
||||
}
|
||||
&:not(:last-child) { border-right : 1px solid black; }
|
||||
|
||||
&:last-child {
|
||||
border-radius: 0 0.5em 0.5em 0;
|
||||
}
|
||||
&:last-child { border-radius : 0 0.5em 0.5em 0; }
|
||||
}
|
||||
|
||||
.badge {
|
||||
background-color: #dddddd;
|
||||
border-radius: .5em;
|
||||
font-size: .9em;
|
||||
margin: 2px;
|
||||
padding: .3em;
|
||||
padding : 0.3em;
|
||||
margin : 2px;
|
||||
font-size : 0.9em;
|
||||
background-color : #DDDDDD;
|
||||
border-radius : 0.5em;
|
||||
|
||||
.icon {
|
||||
#groupedIcon
|
||||
}
|
||||
#groupedIcon; }
|
||||
}
|
||||
|
||||
.input-group {
|
||||
height: ~"calc(.9em + 4px + .6em)";
|
||||
height : ~'calc(.9em + 4px + .6em)';
|
||||
|
||||
input {
|
||||
border-radius: .5em 0 0 .5em;
|
||||
}
|
||||
input { border-radius : 0.5em 0 0 0.5em; }
|
||||
|
||||
input:last-child {
|
||||
border-radius: .5em;
|
||||
}
|
||||
input:last-child { border-radius : 0.5em; }
|
||||
|
||||
.value {
|
||||
width: 7.5vw;
|
||||
min-width: 75px;
|
||||
height: 100%;
|
||||
width : 7.5vw;
|
||||
min-width : 75px;
|
||||
height : 100%;
|
||||
}
|
||||
|
||||
.invalid:focus {
|
||||
background-color: pink;
|
||||
}
|
||||
.invalid:focus { background-color : pink; }
|
||||
|
||||
.icon {
|
||||
#groupedIcon;
|
||||
height: 97%;
|
||||
font-size: .8em;
|
||||
right: 1px;
|
||||
top: -.54em;
|
||||
top : -0.54em;
|
||||
right : 1px;
|
||||
height : 97%;
|
||||
font-size : 0.8em;
|
||||
|
||||
i {
|
||||
font-size: 1.125em;
|
||||
}
|
||||
i { font-size : 1.125em; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,9 +71,9 @@ const Homebrew = createClass({
|
||||
<Route path='/new/:id' element={<WithRoute el={NewPage} brew={this.props.brew} userThemes={this.props.userThemes}/>} />
|
||||
<Route path='/new' element={<WithRoute el={NewPage} userThemes={this.props.userThemes}/> } />
|
||||
<Route path='/user/:username' element={<WithRoute el={UserPage} brews={this.props.brews} />} />
|
||||
<Route path='/changelog' element={<WithRoute el={SharePage} brew={this.props.brew} />} />
|
||||
<Route path='/faq' element={<WithRoute el={SharePage} brew={this.props.brew} />} />
|
||||
<Route path='/migrate' element={<WithRoute el={SharePage} brew={this.props.brew} />} />
|
||||
<Route path='/changelog' element={<WithRoute el={SharePage} brew={this.props.brew} disableMeta={true} />} />
|
||||
<Route path='/faq' element={<WithRoute el={SharePage} brew={this.props.brew} disableMeta={true} />} />
|
||||
<Route path='/migrate' element={<WithRoute el={SharePage} brew={this.props.brew} disableMeta={true} />} />
|
||||
<Route path='/account' element={<WithRoute el={AccountPage} brew={this.props.brew} accountDetails={this.props.brew.accountDetails} />} />
|
||||
<Route path='/legacy' element={<WithRoute el={HomePage} brew={this.props.brew} />} />
|
||||
<Route path='/error' element={<WithRoute el={ErrorPage} brew={this.props.brew} />} />
|
||||
|
||||
@@ -18,7 +18,8 @@ const SharePage = createClass({
|
||||
displayName : 'SharePage',
|
||||
getDefaultProps : function() {
|
||||
return {
|
||||
brew : DEFAULT_BREW_LOAD,
|
||||
brew : DEFAULT_BREW_LOAD,
|
||||
disableMeta : false
|
||||
};
|
||||
},
|
||||
|
||||
@@ -68,13 +69,21 @@ const SharePage = createClass({
|
||||
},
|
||||
|
||||
render : function(){
|
||||
const titleStyle = this.props.disableMeta ? { cursor: 'default' } : {};
|
||||
const titleEl = <Nav.item className='brewTitle' style={titleStyle}>{this.props.brew.title}</Nav.item>;
|
||||
|
||||
return <div className='sharePage sitePage'>
|
||||
<Meta name='robots' content='noindex, nofollow' />
|
||||
<Navbar>
|
||||
<Nav.section className='titleSection'>
|
||||
<MetadataNav brew={this.props.brew}>
|
||||
<Nav.item className='brewTitle'>{this.props.brew.title}</Nav.item>
|
||||
</MetadataNav>
|
||||
{
|
||||
this.props.disableMeta ?
|
||||
titleEl
|
||||
:
|
||||
<MetadataNav brew={this.props.brew}>
|
||||
{titleEl}
|
||||
</MetadataNav>
|
||||
}
|
||||
</Nav.section>
|
||||
|
||||
<Nav.section>
|
||||
|
||||
4481
package-lock.json
generated
4481
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
@@ -105,7 +105,7 @@
|
||||
"less": "^3.13.1",
|
||||
"lodash": "^4.17.21",
|
||||
"marked": "11.2.0",
|
||||
"marked-emoji": "^1.4.1",
|
||||
"marked-emoji": "^1.4.2",
|
||||
"marked-extended-tables": "^1.0.8",
|
||||
"marked-gfm-heading-id": "^3.2.0",
|
||||
"marked-smartypants-lite": "^1.0.2",
|
||||
@@ -117,22 +117,22 @@
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-frame-component": "^4.1.3",
|
||||
"react-router-dom": "6.25.1",
|
||||
"react-router-dom": "6.26.0",
|
||||
"sanitize-filename": "1.6.3",
|
||||
"superagent": "^9.0.2",
|
||||
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@stylistic/stylelint-plugin": "^3.0.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-jest": "^28.6.0",
|
||||
"eslint-plugin-jest": "^28.8.0",
|
||||
"eslint-plugin-react": "^7.35.0",
|
||||
"jest": "^29.7.0",
|
||||
"jest-expect-message": "^1.1.3",
|
||||
"postcss-less": "^6.0.0",
|
||||
"stylelint": "^15.11.0",
|
||||
"stylelint-config-recess-order": "^4.6.0",
|
||||
"stylelint-config-recommended": "^13.0.0",
|
||||
"stylelint-stylistic": "^0.4.3",
|
||||
"stylelint": "^16.8.0",
|
||||
"stylelint-config-recess-order": "^5.0.1",
|
||||
"stylelint-config-recommended": "^14.0.1",
|
||||
"supertest": "^7.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,8 +39,10 @@ if(typeof window !== 'undefined'){
|
||||
//Autocompletion
|
||||
require('codemirror/addon/hint/show-hint.js');
|
||||
|
||||
const foldCode = require('./fold-code');
|
||||
foldCode.registerHomebreweryHelper(CodeMirror);
|
||||
const foldPagesCode = require('./fold-pages');
|
||||
foldPagesCode.registerHomebreweryHelper(CodeMirror);
|
||||
const foldCSSCode = require('./fold-css');
|
||||
foldCSSCode.registerHomebreweryHelper(CodeMirror);
|
||||
}
|
||||
|
||||
const CodeEditor = createClass({
|
||||
@@ -411,11 +413,11 @@ const CodeEditor = createClass({
|
||||
foldOptions : function(cm){
|
||||
return {
|
||||
scanUp : true,
|
||||
rangeFinder : CodeMirror.fold.homebrewery,
|
||||
rangeFinder : this.props.language === 'css' ? CodeMirror.fold.homebrewerycss : CodeMirror.fold.homebrewery,
|
||||
widget : (from, to)=>{
|
||||
let text = '';
|
||||
let currentLine = from.line;
|
||||
const maxLength = 50;
|
||||
let maxLength = 50;
|
||||
|
||||
let foldPreviewText = '';
|
||||
while (currentLine <= to.line && text.length <= maxLength) {
|
||||
@@ -430,10 +432,15 @@ const CodeEditor = createClass({
|
||||
}
|
||||
}
|
||||
text = foldPreviewText || `Lines ${from.line+1}-${to.line+1}`;
|
||||
text = text.replace('{', '').trim();
|
||||
|
||||
// Truncate data URLs at `data:`
|
||||
const startOfData = text.indexOf('data:');
|
||||
if(startOfData > 0)
|
||||
maxLength = Math.min(startOfData + 5, maxLength);
|
||||
|
||||
text = text.trim();
|
||||
if(text.length > maxLength)
|
||||
text = `${text.substr(0, maxLength)}...`;
|
||||
text = `${text.slice(0, maxLength)}...`;
|
||||
|
||||
return `\u21A4 ${text} \u21A6`;
|
||||
}
|
||||
@@ -450,3 +457,4 @@ const CodeEditor = createClass({
|
||||
});
|
||||
|
||||
module.exports = CodeEditor;
|
||||
|
||||
|
||||
44
shared/naturalcrit/codeEditor/fold-css.js
Normal file
44
shared/naturalcrit/codeEditor/fold-css.js
Normal file
@@ -0,0 +1,44 @@
|
||||
module.exports = {
|
||||
registerHomebreweryHelper : function(CodeMirror) {
|
||||
CodeMirror.registerHelper('fold', 'homebrewerycss', function(cm, start) {
|
||||
|
||||
// BRACE FOLDING
|
||||
const startMatcher = /\{[ \t]*$/;
|
||||
const endMatcher = /\}[ \t]*$/;
|
||||
const activeLine = cm.getLine(start.line);
|
||||
|
||||
|
||||
if(activeLine.match(startMatcher)) {
|
||||
const lastLineNo = cm.lastLine();
|
||||
let end = start.line + 1;
|
||||
let braceCount = 1;
|
||||
|
||||
while (end < lastLineNo) {
|
||||
const curLine = cm.getLine(end);
|
||||
if(curLine.match(startMatcher)) braceCount++;
|
||||
if(curLine.match(endMatcher)) braceCount--;
|
||||
if(braceCount == 0) break;
|
||||
++end;
|
||||
}
|
||||
|
||||
return {
|
||||
from : CodeMirror.Pos(start.line, 0),
|
||||
to : CodeMirror.Pos(end, cm.getLine(end).length)
|
||||
};
|
||||
}
|
||||
|
||||
// @import and data-url folding
|
||||
const importMatcher = /^@import.*?;/;
|
||||
const dataURLMatcher = /url\(.*?data\:.*\)/;
|
||||
|
||||
if(activeLine.match(importMatcher) || activeLine.match(dataURLMatcher)) {
|
||||
return {
|
||||
from : CodeMirror.Pos(start.line, 0),
|
||||
to : CodeMirror.Pos(start.line, activeLine.length)
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -28,17 +28,18 @@ const mathParser = new MathParser({
|
||||
round : true,
|
||||
floor : true,
|
||||
ceil : true,
|
||||
abs : true,
|
||||
|
||||
sin : false, cos : false, tan : false, asin : false, acos : false,
|
||||
atan : false, sinh : false, cosh : false, tanh : false, asinh : false,
|
||||
acosh : false, atanh : false, sqrt : false, cbrt : false, log : false,
|
||||
log2 : false, ln : false, lg : false, log10 : false, expm1 : false,
|
||||
log1p : false, abs : false, trunc : false, join : false, sum : false,
|
||||
log1p : false, trunc : false, join : false, sum : false, indexOf : false,
|
||||
'-' : false, '+' : false, exp : false, not : false, length : false,
|
||||
'!' : false, sign : false, random : false, fac : false, min : false,
|
||||
max : false, hypot : false, pyt : false, pow : false, atan2 : false,
|
||||
'if' : false, gamma : false, roundTo : false, map : false, fold : false,
|
||||
filter : false, indexOf : false,
|
||||
filter : false,
|
||||
|
||||
remainder : false, factorial : false,
|
||||
comparison : false, concatenate : false,
|
||||
@@ -46,6 +47,16 @@ const mathParser = new MathParser({
|
||||
array : false, fndef : false
|
||||
}
|
||||
});
|
||||
// Add sign function
|
||||
mathParser.functions.sign = function (a) {
|
||||
if(a >= 0) return '+';
|
||||
return '-';
|
||||
};
|
||||
// Add signed function
|
||||
mathParser.functions.signed = function (a) {
|
||||
if(a >= 0) return `+${a}`;
|
||||
return `${a}`;
|
||||
};
|
||||
|
||||
//Processes the markdown within an HTML block if it's just a class-wrapper
|
||||
renderer.html = function (html) {
|
||||
@@ -441,7 +452,7 @@ const replaceVar = function(input, hoist=false, allowUnresolved=false) {
|
||||
const label = match[2];
|
||||
|
||||
//v=====--------------------< HANDLE MATH >-------------------=====v//
|
||||
const mathRegex = /[a-z]+\(|[+\-*/^()]/g;
|
||||
const mathRegex = /[a-z]+\(|[+\-*/^(),]/g;
|
||||
const matches = label.split(mathRegex);
|
||||
const mathVars = matches.filter((match)=>isNaN(match))?.map((s)=>s.trim()); // Capture any variable names
|
||||
|
||||
@@ -451,7 +462,7 @@ const replaceVar = function(input, hoist=false, allowUnresolved=false) {
|
||||
mathVars?.forEach((variable)=>{
|
||||
const foundVar = lookupVar(variable, globalPageNumber, hoist);
|
||||
if(foundVar && foundVar.resolved && foundVar.content && !isNaN(foundVar.content)) // Only subsitute math values if fully resolved, not empty strings, and numbers
|
||||
replacedLabel = replacedLabel.replaceAll(variable, foundVar.content);
|
||||
replacedLabel = replacedLabel.replaceAll(new RegExp(`(?<!\\w)(${variable})(?!\\w)`, 'g'), foundVar.content);
|
||||
});
|
||||
|
||||
try {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const stylelint = require('stylelint');
|
||||
const { isNumber } = require('stylelint/lib/utils/validateTypes');
|
||||
const { isNumber } = require('stylelint/lib/utils/validateTypes.cjs');
|
||||
|
||||
const { report, ruleMessages, validateOptions } = stylelint.utils;
|
||||
const ruleName = 'naturalcrit/declaration-block-multi-line-min-declarations';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const stylelint = require('stylelint');
|
||||
const { isNumber } = require('stylelint/lib/utils/validateTypes');
|
||||
const { isNumber } = require('stylelint/lib/utils/validateTypes.cjs');
|
||||
|
||||
const { report, ruleMessages, validateOptions } = stylelint.utils;
|
||||
const ruleName = 'naturalcrit/declaration-colon-min-space-before';
|
||||
|
||||
@@ -370,4 +370,36 @@ describe('Cross-page variables', ()=>{
|
||||
const rendered = renderAllPages([source0, source1]).join('\n\\page\n').trimReturns();
|
||||
expect(rendered, `Input:\n${[source0, source1].join('\n\\page\n')}`, { showPrefix: false }).toBe('<p>two</p><p>one</p>\\page<p>two</p>');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Math function parameter handling', ()=>{
|
||||
it('allows variables in single-parameter functions', function() {
|
||||
const source = '[var]:4.1\n\n$[floor(var)]';
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<p>4</p>`);
|
||||
});
|
||||
it('allows one variable and a number in two-parameter functions', function() {
|
||||
const source = '[var]:4\n\n$[min(1,var)]';
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<p>1</p>`);
|
||||
});
|
||||
it('allows two variables in two-parameter functions', function() {
|
||||
const source = '[var1]:4\n\n[var2]:8\n\n$[min(var1,var2)]';
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<p>4</p>`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variable names that are subsets of other names', ()=>{
|
||||
it('do not conflict with function names', function() {
|
||||
const source = `[a]: -1\n\n$[abs(a)]`;
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered).toBe('<p>1</p>');
|
||||
});
|
||||
|
||||
it('do not conflict with other variable names', function() {
|
||||
const source = `[ab]: 2\n\n[aba]: 8\n\n[ba]: 4\n\n$[ab + aba + ba]`;
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered).toBe('<p>14</p>');
|
||||
});
|
||||
});
|
||||
@@ -892,6 +892,9 @@ h6,
|
||||
.useColumns(0.96, @fillMode: balance);
|
||||
}
|
||||
}
|
||||
.toc.wide li {
|
||||
break-inside: auto;
|
||||
}
|
||||
}
|
||||
|
||||
// *****************************
|
||||
|
||||
Reference in New Issue
Block a user