chore: add JS/ESLint toolchain, refactor onclick to event delegation
- Add ESLint config for web/ui (flat config, golangci-lint-compatible) - Add js-lint task to mise.toml (npm run lint in web/ui) - Add ESLint check to check-toolchain.sh - Add .golangci.yml for golangci-lint v2 with correct exclusions - Refactor app.js: replace inline onclick with data-action + event delegation - Add null checks and HTTP status checks to browseWavs - Add web/ui/node_modules/ to .gitignore
This commit is contained in:
@@ -25,5 +25,8 @@ wavs
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|
||||||
|
# JS dependencies
|
||||||
|
web/ui/node_modules/
|
||||||
|
|
||||||
# Temp
|
# Temp
|
||||||
/tmp/
|
/tmp/
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
version: "2"
|
||||||
|
|
||||||
|
linters:
|
||||||
|
default: none
|
||||||
|
enable:
|
||||||
|
- errcheck
|
||||||
|
- govet
|
||||||
|
- staticcheck
|
||||||
|
- unused
|
||||||
|
exclusions:
|
||||||
|
paths:
|
||||||
|
- web/ui
|
||||||
|
- electron
|
||||||
|
- third_party/akaiutil/
|
||||||
@@ -11,7 +11,8 @@ build = "go build -buildvcs=false -o fetch ."
|
|||||||
akaiutil = "make -C third_party/akaiutil"
|
akaiutil = "make -C third_party/akaiutil"
|
||||||
all = { run = "go build -buildvcs=false -o fetch . && make -C third_party/akaiutil" }
|
all = { run = "go build -buildvcs=false -o fetch . && make -C third_party/akaiutil" }
|
||||||
serve = { run = "go build -buildvcs=false -o fetch . && ./fetch serve" }
|
serve = { run = "go build -buildvcs=false -o fetch . && ./fetch serve" }
|
||||||
lint = "go vet ./..."
|
lint = "golangci-lint run"
|
||||||
|
js-lint = "cd web/ui && npm run lint"
|
||||||
electron-deps = "cd electron && npm install"
|
electron-deps = "cd electron && npm install"
|
||||||
electron-dev = { run = "go build -buildvcs=false -o fetch . && cd electron && npx electron ." }
|
electron-dev = { run = "go build -buildvcs=false -o fetch . && cd electron && npx electron ." }
|
||||||
electron-build = { run = "go build -buildvcs=false -o fetch . && make -C third_party/akaiutil && cd electron && npx electron-builder --dir" }
|
electron-build = { run = "go build -buildvcs=false -o fetch . && make -C third_party/akaiutil && cd electron && npx electron-builder --dir" }
|
||||||
|
|||||||
@@ -123,5 +123,16 @@ else
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== JS Linting (ESLint) ==="
|
||||||
|
if [ -f web/ui/node_modules/.bin/eslint ]; then
|
||||||
|
ok "ESLint installed at web/ui/node_modules/.bin/eslint"
|
||||||
|
eslint_ver=$(cd web/ui && ./node_modules/.bin/eslint --version 2>/dev/null)
|
||||||
|
ok "ESLint: $eslint_ver"
|
||||||
|
else
|
||||||
|
warn "ESLint not installed (needed for web UI linting)"
|
||||||
|
echo " Install: cd web/ui && npm install"
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "=== Core toolchain check complete ==="
|
echo "=== Core toolchain check complete ==="
|
||||||
|
|||||||
+17
-3
@@ -46,8 +46,8 @@ function renderResults(items) {
|
|||||||
<span>${r.downloads.toLocaleString()} downloads</span>
|
<span>${r.downloads.toLocaleString()} downloads</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<button class="btn-dl" onclick="downloadItem('${esc(r.identifier)}')">Download ISOs</button>
|
<button class="btn-dl" data-action="download" data-identifier="${esc(r.identifier)}">Download ISOs</button>
|
||||||
<button class="btn-list" onclick="listItem('${esc(r.identifier)}')">List Files</button>
|
<button class="btn-list" data-action="list" data-identifier="${esc(r.identifier)}">List Files</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="list-${sanitize(r.identifier)}" class="file-list"></div>
|
<div id="list-${sanitize(r.identifier)}" class="file-list"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -218,7 +218,7 @@ async function browseWavs() {
|
|||||||
list.innerHTML = data.map(f => `
|
list.innerHTML = data.map(f => `
|
||||||
<div class="wav-item" data-file="${esc(f)}">
|
<div class="wav-item" data-file="${esc(f)}">
|
||||||
<span class="wav-name" title="${esc(f)}">${esc(f)}</span>
|
<span class="wav-name" title="${esc(f)}">${esc(f)}</span>
|
||||||
<button class="wav-play-btn" onclick="playWav('${esc(f)}')">Play</button>
|
<button class="wav-play-btn" data-action="play" data-wav="${esc(f)}">Play</button>
|
||||||
</div>
|
</div>
|
||||||
`).join('');
|
`).join('');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -332,3 +332,17 @@ function formatBytes(bytes) {
|
|||||||
|
|
||||||
// Initial load
|
// Initial load
|
||||||
doSearch();
|
doSearch();
|
||||||
|
|
||||||
|
// Event delegation for dynamically generated buttons
|
||||||
|
document.addEventListener('click', function(e) {
|
||||||
|
const btn = e.target.closest('[data-action]');
|
||||||
|
if (!btn) return;
|
||||||
|
const action = btn.dataset.action;
|
||||||
|
if (action === 'download') {
|
||||||
|
downloadItem(btn.dataset.identifier);
|
||||||
|
} else if (action === 'list') {
|
||||||
|
listItem(btn.dataset.identifier);
|
||||||
|
} else if (action === 'play') {
|
||||||
|
playWav(btn.dataset.wav);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
const globals = require('globals');
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
files: ['**/*.js'],
|
||||||
|
languageOptions: {
|
||||||
|
ecmaVersion: 2022,
|
||||||
|
sourceType: 'script',
|
||||||
|
globals: {
|
||||||
|
...globals.browser,
|
||||||
|
AudioContext: 'readonly',
|
||||||
|
requestAnimationFrame: 'readonly',
|
||||||
|
cancelAnimationFrame: 'readonly',
|
||||||
|
fetch: 'readonly',
|
||||||
|
EventSource: 'readonly',
|
||||||
|
document: 'readonly',
|
||||||
|
console: 'readonly',
|
||||||
|
setTimeout: 'readonly',
|
||||||
|
Math: 'readonly',
|
||||||
|
JSON: 'readonly',
|
||||||
|
location: 'readonly',
|
||||||
|
encodeURIComponent: 'readonly',
|
||||||
|
decodeURIComponent: 'readonly',
|
||||||
|
parseInt: 'readonly',
|
||||||
|
Number: 'readonly',
|
||||||
|
Promise: 'readonly',
|
||||||
|
Object: 'readonly',
|
||||||
|
Array: 'readonly',
|
||||||
|
Map: 'readonly',
|
||||||
|
process: 'readonly',
|
||||||
|
__dirname: 'readonly',
|
||||||
|
require: 'readonly',
|
||||||
|
module: 'readonly',
|
||||||
|
exports: 'readonly'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
"no-unused-vars": ["warn", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }],
|
||||||
|
"no-redeclare": "warn",
|
||||||
|
"no-unreachable": "warn",
|
||||||
|
"eqeqeq": ["error", "always"],
|
||||||
|
"prefer-const": "warn"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
Generated
+1098
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"name": "akai-utils-web-ui",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Web UI for AKAI Utils",
|
||||||
|
"scripts": {
|
||||||
|
"lint": "eslint *.js"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"eslint": "^9.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user