chore: add a pipeline for linting JS and CoffeeScript files (#2176)

This commit is contained in:
Nico Miguelino
2024-12-26 13:33:09 -08:00
committed by GitHub
parent bbc779fd6b
commit aa0ad68050
11 changed files with 2968 additions and 44 deletions

35
.github/workflows/javascript-lint.yaml vendored Normal file
View File

@@ -0,0 +1,35 @@
name: Run JavaScript and CoffeeScript Linter
on:
push:
branches: [ master ]
paths:
- '**/*.js'
- '**/*.coffee'
- '**/*.mjs'
- '.github/workflows/javascript-lint.yaml'
pull_request:
branches: [ master ]
paths:
- '**/*.js'
- '**/*.coffee'
- '**/*.mjs'
- '.github/workflows/javascript-lint.yaml'
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run ESLint
run: npm run lint

6
.gitignore vendored
View File

@@ -56,3 +56,9 @@ db.sqlite3
# Django
staticfiles/
# ESLint
.eslintcache
# Linting
.coffeelint.json

31
coffeelint.json Normal file
View File

@@ -0,0 +1,31 @@
{
"arrow_spacing": {
"level": "error"
},
"braces_spacing": {
"level": "error",
"spaces": 0
},
"camel_case_classes": {
"level": "error"
},
"no_tabs": {
"level": "error"
},
"no_trailing_whitespace": {
"level": "error",
"allowed_in_comments": false,
"allowed_in_empty_lines": false
},
"max_line_length": {
"value": 120,
"level": "error"
},
"missing_fat_arrows": {
"level": "warn"
},
"indentation": {
"value": 2,
"level": "error"
}
}

36
eslint.config.mjs Normal file
View File

@@ -0,0 +1,36 @@
export default [
{
ignores: [
'dist/**',
'static/dist/**',
'static/spec/**',
'static/js/backbone-0.9.10.min.js',
'static/js/moment.js',
'static/js/underscore-1.4.3.min.js',
'static/js/base64js.min.js',
'static/js/bootstrap.min.js',
'static/js/bootstrap-datepicker.js',
'static/js/bootstrap-timepicker.js',
'static/js/popper.min.js',
'static/js/jquery-3.7.1.min.js',
'static/js/jquery-ui-1.10.1.custom.min.js',
'static/js/jquery.fileupload.js',
'static/js/jquery.iframe-transport.js',
],
},
{
files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
rules: {
'semi': ['error', 'always'],
'quotes': ['error', 'single'],
'indent': ['error', 2],
'no-unused-vars': 'warn',
'no-console': 'warn',
'no-debugger': 'warn'
}
}
];

2804
package-lock.json generated
View File

File diff suppressed because it is too large Load Diff

View File

@@ -3,13 +3,15 @@
"version": "1.0.0",
"scripts": {
"dev": "webpack --watch --config webpack.dev.js",
"build": "webpack --config webpack.prod.js"
"build": "webpack --config webpack.prod.js",
"lint": "coffeelint static/js/*.coffee && eslint ."
},
"dependencies": {
"bootstrap": "^4.3.1",
"css-toggle-switch": "^4.1.0"
},
"devDependencies": {
"@coffeelint/cli": "^5.2.11",
"coffee-loader": "^0.9.0",
"coffeescript": "^1.12.7",
"css-loader": "^7.1.2",
@@ -18,6 +20,8 @@
"sass-loader": "^16.0.3",
"webpack": "^5.96.1",
"webpack-cli": "^5.1.4",
"webpack-merge": "^6.0.1"
"webpack-merge": "^6.0.1",
"eslint": "^8.56.0",
"eslint-plugin-react": "^7.33.2"
}
}

View File

@@ -72,7 +72,10 @@ durationSecondsToHumanReadable = (secs) ->
return durationString
url_test = (v) -> /(http|https|rtsp|rtmp):\/\/[\w-]+(\.?[\w-]+)+([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?/.test v
url_test = (v) ->
urlPattern = /(http|https|rtsp|rtmp):\/\/[\w-]+(\.?[\w-]+)+([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?/
urlPattern.test v
get_filename = (v) -> (v.replace /[\/\\\s]+$/g, '').replace /^.*[\\\/]/g, ''
truncate_str = (v) -> v.replace /(.{100})..+/, "$1..."
insertWbr = (v) -> (v.replace /\//g, '/<wbr>').replace /\&/g, '&amp;<wbr>'
@@ -100,8 +103,8 @@ API.Asset = class Asset extends Backbone.Model
active: =>
if @get('is_enabled') and @get('start_date') and @get('end_date')
at = now()
start_date = new Date(@get('start_date'));
end_date = new Date(@get('end_date'));
start_date = new Date(@get('start_date'))
end_date = new Date(@get('end_date'))
return start_date <= at <= end_date
else
return false
@@ -125,7 +128,7 @@ API.Assets = class Assets extends Backbone.Collection
# Views
API.View = {};
API.View = {}
API.View.AddAssetView = class AddAssetView extends Backbone.View
$f: (field) => @$ "[name='#{field}']" # get field element
@@ -146,7 +149,8 @@ API.View.AddAssetView = class AddAssetView extends Backbone.View
viewmodel:(model) =>
for which in ['start', 'end']
@$fv "#{which}_date", (moment (@$fv "#{which}_date_date") + " " + (@$fv "#{which}_date_time"), dateSettings.fullDate).toDate().toISOString()
date = (@$fv "#{which}_date_date") + " " + (@$fv "#{which}_date_time")
@$fv "#{which}_date", (moment date, dateSettings.fullDate).toDate().toISOString()
for field in model.fields when not (@$f field).prop 'disabled'
model.set field, (@$fv field), silent:yes
@@ -346,7 +350,8 @@ API.View.EditAssetView = class EditAssetView extends Backbone.View
viewmodel: =>
for which in ['start', 'end']
@$fv "#{which}_date", (moment (@$fv "#{which}_date_date") + " " + (@$fv "#{which}_date_time"), dateSettings.fullDate).toDate().toISOString()
date = (@$fv "#{which}_date_date") + " " + (@$fv "#{which}_date_time")
@$fv "#{which}_date", (moment date, dateSettings.fullDate).toDate().toISOString()
for field in @model.fields when not (@$f field).prop 'disabled'
@model.set field, (@$fv field), silent:yes

View File

@@ -96,7 +96,10 @@ $().ready ->
($ "#request-error .alert").show()
($ "#request-error .alert").addClass "alert-success"
($ "#request-error .alert").removeClass "alert-danger"
($ "#request-error .msg").text "Device shutdown has started successfully. Soon you will be able to unplug the power from your Raspberry Pi."
($ "#request-error .msg").text """
Device shutdown has started successfully.
Soon you will be able to unplug the power from your Raspberry Pi.
"""
.fail (data, e) ->
($ "#request-error .alert").show()
($ "#request-error .alert").addClass "alert-danger"

View File

@@ -1,36 +1,36 @@
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const path = require("path");
const path = require('path');
module.exports = {
entry: {
"anthias": "./static/js/anthias.coffee",
"settings": "./static/js/settings.coffee",
},
output: {
path: path.resolve(__dirname, "static/dist"),
filename: "js/[name].js",
clean: true,
},
plugins: [
new MiniCssExtractPlugin({
filename: "css/anthias.css"
})
],
module: {
rules: [
{
test: /\.coffee$/,
use: ["coffee-loader"]
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"sass-loader"
]
}
entry: {
'anthias': './static/js/anthias.coffee',
'settings': './static/js/settings.coffee',
},
output: {
path: path.resolve(__dirname, 'static/dist'),
filename: 'js/[name].js',
clean: true,
},
plugins: [
new MiniCssExtractPlugin({
filename: 'css/anthias.css'
})
],
module: {
rules: [
{
test: /\.coffee$/,
use: ['coffee-loader']
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader'
]
},
}
]
},
};

View File

@@ -1,7 +1,7 @@
const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
devtool: "source-map",
mode: "development",
devtool: 'source-map',
mode: 'development',
});

View File

@@ -2,5 +2,5 @@ const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'production',
mode: 'production',
});