0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2025-12-24 18:32:41 +00:00

Merge branch 'master' into pr/2755

This commit is contained in:
Trevor Buckner
2023-05-30 17:18:03 -04:00
10 changed files with 702 additions and 615 deletions

View File

@@ -1,42 +1,48 @@
{
"extends": ["stylelint-config-recess-order"],
"extends": [
"stylelint-config-recess-order",
"stylelint-config-recommended"],
"plugins": [
"stylelint-stylistic",
"./stylelint_plugins/align-colons.js",
"./stylelint_plugins/declaration-block-multi-line-min-declarations",
"./stylelint_plugins/declaration-colon-min-space-before"
"./stylelint_plugins/declaration-colon-align.js",
"./stylelint_plugins/declaration-colon-min-space-before",
"./stylelint_plugins/declaration-block-multi-line-min-declarations"
],
"customSyntax": "postcss-less",
"rules": {
"stylistic/indentation": "tab",
"stylistic/string-quotes": "double",
"no-duplicate-selectors": true,
"stylistic/color-hex-case": "upper",
"color-hex-length": "long",
"stylistic/selector-combinator-space-after": "always",
"stylistic/selector-combinator-space-before": "always",
"selector-attribute-quotes": "always",
"stylistic/selector-attribute-operator-space-before": "always",
"stylistic/selector-attribute-operator-space-after": "always",
"stylistic/selector-attribute-brackets-space-inside": "never",
"stylistic/block-opening-brace-space-before": "always",
"stylistic/declaration-block-trailing-semicolon": "always",
"naturalcrit/declaration-colon-min-space-before": 1,
"stylistic/declaration-colon-space-after": "always",
"stylistic/number-leading-zero": "always",
"function-url-quotes": "always",
"function-url-scheme-disallowed-list": ["data"],
"font-weight-notation": "named-where-possible",
"font-family-name-quotes": "always-unless-keyword",
"comment-whitespace-inside": "always",
"selector-pseudo-element-colon-notation": "double",
"stylistic/selector-pseudo-class-parentheses-space-inside": "never",
"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/align-colons": true,
"naturalcrit/declaration-block-multi-line-min-declarations" : 1
"no-descending-specificity" : null,
"at-rule-no-unknown" : null,
"function-no-unknown" : null,
"font-family-no-missing-generic-family-keyword" : null,
"font-weight-notation" : "named-where-possible",
"font-family-name-quotes" : "always-unless-keyword",
"stylistic/indentation" : "tab",
"no-duplicate-selectors" : true,
"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",
"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",
"naturalcrit/declaration-colon-min-space-before" : 1,
"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",
"naturalcrit/declaration-colon-align" : true,
"naturalcrit/declaration-block-multi-line-min-declarations": 1
}
}

View File

@@ -140,7 +140,7 @@ const StringArrayEditor = createClass({
</div>
</div>
{this.props.notes ? this.props.notes.map((n)=><p><small>{n}</small></p>) : null}
{this.props.notes ? this.props.notes.map((n, index)=><p key={index}><small>{n}</small></p>) : null}
</div>
</div>;
}

927
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -78,10 +78,10 @@
]
},
"dependencies": {
"@babel/core": "^7.21.8",
"@babel/plugin-transform-runtime": "^7.21.4",
"@babel/preset-env": "^7.21.5",
"@babel/preset-react": "^7.18.6",
"@babel/core": "^7.22.1",
"@babel/plugin-transform-runtime": "^7.22.2",
"@babel/preset-env": "^7.22.2",
"@babel/preset-react": "^7.22.3",
"@googleapis/drive": "^5.1.0",
"body-parser": "^1.20.2",
"classnames": "^2.3.2",
@@ -101,7 +101,7 @@
"marked-extended-tables": "^1.0.6",
"markedLegacy": "npm:marked@^0.3.19",
"moment": "^2.29.4",
"mongoose": "^7.1.2",
"mongoose": "^7.2.1",
"nanoid": "3.3.4",
"nconf": "^0.12.0",
"npm": "^9.6.7",
@@ -114,7 +114,7 @@
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
},
"devDependencies": {
"eslint": "^8.40.0",
"eslint": "^8.41.0",
"eslint-plugin-jest": "^27.2.1",
"eslint-plugin-react": "^7.32.2",
"jest": "^29.5.0",
@@ -122,7 +122,7 @@
"postcss-less": "^6.0.0",
"stylelint": "^15.6.2",
"stylelint-config-recess-order": "^4.0.0",
"stylelint-config-standard": "^33.0.0",
"stylelint-config-recommended": "^12.0.0",
"stylelint-stylistic": "^0.4.2",
"supertest": "^6.3.3"
}

View File

@@ -138,7 +138,9 @@ fs.emptyDirSync('./build');
//In development set up a watch server and livereload
if(isDev){
livereload('./build');
watchFile('./server.js', {
watch : ['./client', './server', './themes'] // Watch additional folders if you want
watchFile('./server.js', { // Rebuild when change detected to this file or any nested directory from here
ignore : ['./build'], // Ignore ./build or it will rebuild again
ext : 'less', // Other extensions to watch (only .js/.json/.jsx by default)
//watch: ['./client', './server', './themes'], // Watch additional folders if you want
});
}

View File

@@ -97,11 +97,14 @@ const CodeEditor = createClass({
this.codeMirror = CodeMirror(this.refs.editor, {
lineNumbers : true,
lineWrapping : this.props.wrap,
indentWithTabs : true,
indentWithTabs : false,
tabSize : 2,
smartIndent : false,
historyEventDelay : 250,
scrollPastEnd : true,
extraKeys : {
'Tab' : this.indent,
'Shift-Tab' : this.dedent,
'Ctrl-B' : this.makeBold,
'Cmd-B' : this.makeBold,
'Ctrl-I' : this.makeItalic,
@@ -171,6 +174,19 @@ const CodeEditor = createClass({
this.updateSize();
},
indent : function () {
const cm = this.codeMirror;
if (cm.somethingSelected()) {
cm.execCommand('indentMore');
} else {
cm.execCommand('insertSoftTab');
}
},
dedent : function () {
this.codeMirror.execCommand('indentLess');
},
makeHeader : function (number) {
const selection = this.codeMirror.getSelection();
const header = Array(number).fill('#').join('');

View File

@@ -1,68 +0,0 @@
const stylelint = require('stylelint');
const { report, ruleMessages, validateOptions } = stylelint.utils;
const ruleName = 'naturalcrit/align-colons';
const messages = ruleMessages(ruleName, {
expected: (rule) => `Expected colons aligned within rule "${rule}"`,
});
module.exports = stylelint.createPlugin(ruleName, function getPlugin(primaryOption, secondaryOptionObject, context) {
return function lint(postcssRoot, postcssResult) {
const validOptions = validateOptions(
postcssResult,
ruleName,
{
actual: primaryOption,
possible: [
true,
false
]
}
);
if (!validOptions) { //If the options are invalid, don't lint
return;
}
const isAutoFixing = Boolean(context.fix);
postcssRoot.walkRules(rule => { //Iterate CSS rules
let maxColonPos = 0;
let misaligned = false;
rule.each(declaration => {
if(declaration.type != "decl")
return;
let colonPos = declaration.prop.length + declaration.raws.between.indexOf(":");
if (maxColonPos > 0 && colonPos != maxColonPos) {
misaligned = true;
}
maxColonPos = Math.max(maxColonPos, colonPos);
});
if(misaligned) {
if (isAutoFixing) { //We are in “fix” mode
rule.each(declaration => {
if(declaration.type != "decl")
return;
declaration.raws.between = " ".repeat(maxColonPos - declaration.prop.length) + ":" + declaration.raws.between.split(":")[1];
})
} else { //We are in “report only” mode
report({
ruleName,
result: postcssResult,
message: messages.expected(rule.selector), // Build the reported message
node: rule, // Specify the reported node
word: rule.selector, // Which exact word caused the error? This positions the error properly
});
}
}
});
};
});
module.exports.ruleName = ruleName;
module.exports.messages = messages;

View File

@@ -4,50 +4,54 @@ const { isNumber } = require('stylelint/lib/utils/validateTypes');
const { report, ruleMessages, validateOptions } = stylelint.utils;
const ruleName = 'naturalcrit/declaration-block-multi-line-min-declarations';
const messages = ruleMessages(ruleName, {
expected: (decls) => `Rule with ${decls} declaration${decls == 1 ? '' : 's'} should be single line`,
expected : (decls)=>`Rule with ${decls} declaration${decls == 1 ? '' : 's'} should be single line`,
});
module.exports = stylelint.createPlugin(ruleName, function getPlugin(primaryOption, secondaryOptionObject, context) {
return function lint(postcssRoot, postcssResult) {
return function lint(postcssRoot, postcssResult) {
const validOptions = validateOptions(
postcssResult,
ruleName,
{
actual: primaryOption,
possible: [isNumber],
}
);
const validOptions = validateOptions(
postcssResult,
ruleName,
{
actual : primaryOption,
possible : [isNumber],
}
);
if (!validOptions) { //If the options are invalid, don't lint
return;
}
const isAutoFixing = Boolean(context.fix);
if(!validOptions) { //If the options are invalid, don't lint
return;
}
const isAutoFixing = Boolean(context.fix);
postcssRoot.walkRules(rule => { //Iterate CSS rules
postcssRoot.walkRules((rule)=>{ //Iterate CSS rules
//Apply rule only if all children are decls (no nested rules)
if (rule.nodes.length > primaryOption || !rule.nodes.every((node) => node.type === 'decl')) {
return;
}
//Apply rule only if all children are decls (no further nested rules)
if(rule.nodes.length > primaryOption || !rule.nodes.every((node)=>node.type === 'decl')) {
return;
}
if (isAutoFixing) { //We are in “fix” mode
rule.each((decl) => {
decl.raws.before = " ";
});
rule.raws.after = ' ';
} else {
report({
ruleName,
result: postcssResult,
message: messages.expected(rule.nodes.length), // Build the reported message
node: rule, // Specify the reported node
word: rule.selector, // Which exact word caused the error? This positions the error properly
});
}
});
};
//Ignore if already one line
if(!rule.nodes.some((node)=>node.raws.before.includes('\n')) && !rule.raws.after.includes('\n'))
return;
if(isAutoFixing) { //We are in “fix” mode
rule.each((decl)=>{
decl.raws.before = ' ';
});
rule.raws.after = ' ';
} else {
report({
ruleName,
result : postcssResult,
message : messages.expected(rule.nodes.length), // Build the reported message
node : rule, // Specify the reported node
word : rule.selector, // Which exact word caused the error? This positions the error properly
});
}
});
};
});
module.exports.ruleName = ruleName;

View File

@@ -0,0 +1,68 @@
const stylelint = require('stylelint');
const { report, ruleMessages, validateOptions } = stylelint.utils;
const ruleName = 'naturalcrit/declaration-colon-align';
const messages = ruleMessages(ruleName, {
expected : (rule)=>`Expected colons aligned within rule "${rule}"`,
});
module.exports = stylelint.createPlugin(ruleName, function getPlugin(primaryOption, secondaryOptionObject, context) {
return function lint(postcssRoot, postcssResult) {
const validOptions = validateOptions(
postcssResult,
ruleName,
{
actual : primaryOption,
possible : [
true,
false
]
}
);
if(!validOptions) { //If the options are invalid, don't lint
return;
}
const isAutoFixing = Boolean(context.fix);
postcssRoot.walkRules((rule)=>{ //Iterate CSS rules
let maxColonPos = 0;
let misaligned = false;
rule.each((declaration)=>{
if(declaration.type != 'decl')
return;
const colonPos = declaration.prop.length + declaration.raws.between.indexOf(':');
if(maxColonPos > 0 && colonPos != maxColonPos) {
misaligned = true;
}
maxColonPos = Math.max(maxColonPos, colonPos);
});
if(misaligned) {
if(isAutoFixing) { //We are in “fix” mode
rule.each((declaration)=>{
if(declaration.type != 'decl')
return;
declaration.raws.between = `${' '.repeat(maxColonPos - declaration.prop.length)}:${declaration.raws.between.split(':')[1]}`;
});
} else { //We are in “report only” mode
report({
ruleName,
result : postcssResult,
message : messages.expected(rule.selector), // Build the reported message
node : rule, // Specify the reported node
word : rule.selector, // Which exact word caused the error? This positions the error properly
});
}
}
});
};
});
module.exports.ruleName = ruleName;
module.exports.messages = messages;

View File

@@ -4,48 +4,48 @@ const { isNumber } = require('stylelint/lib/utils/validateTypes');
const { report, ruleMessages, validateOptions } = stylelint.utils;
const ruleName = 'naturalcrit/declaration-colon-min-space-before';
const messages = ruleMessages(ruleName, {
expected: (num) => `Expected at least ${num} space${num == 1 ? '' : 's'} before ":"`
expected : (num)=>`Expected at least ${num} space${num == 1 ? '' : 's'} before ":"`
});
module.exports = stylelint.createPlugin(ruleName, function getPlugin(primaryOption, secondaryOptionObject, context) {
return function lint(postcssRoot, postcssResult) {
return function lint(postcssRoot, postcssResult) {
const validOptions = validateOptions(
postcssResult,
ruleName,
{
actual: primaryOption,
possible: [isNumber],
}
);
const validOptions = validateOptions(
postcssResult,
ruleName,
{
actual : primaryOption,
possible : [isNumber],
}
);
if (!validOptions) { //If the options are invalid, don't lint
return;
}
const isAutoFixing = Boolean(context.fix);
if(!validOptions) { //If the options are invalid, don't lint
return;
}
const isAutoFixing = Boolean(context.fix);
postcssRoot.walkDecls(decl => { //Iterate CSS declarations
postcssRoot.walkDecls((decl)=>{ //Iterate CSS declarations
let between = decl.raws.between;
const colonIndex = between.indexOf(":");
const between = decl.raws.between;
const colonIndex = between.indexOf(':');
if (between.slice(0, colonIndex).length >= primaryOption) {
return;
}
if (isAutoFixing) { //We are in “fix” mode
decl.raws.between = between.slice(0, colonIndex).replace(/\s*$/, ' '.repeat(primaryOption)) + between.slice(colonIndex)
} else {
report({
ruleName,
result: postcssResult,
message: messages.expected(primaryOption), // Build the reported message
node: decl, // Specify the reported node
word: ":", // Which exact word caused the error? This positions the error properly
});
}
});
};
if(between.slice(0, colonIndex).length >= primaryOption) {
return;
}
if(isAutoFixing) { //We are in “fix” mode
decl.raws.between = between.slice(0, colonIndex).replace(/\s*$/, ' '.repeat(primaryOption)) + between.slice(colonIndex);
} else {
report({
ruleName,
result : postcssResult,
message : messages.expected(primaryOption), // Build the reported message
node : decl, // Specify the reported node
word : ':', // Which exact word caused the error? This positions the error properly
});
}
});
};
});
module.exports.ruleName = ruleName;