diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..7cb66ce --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,35 @@ +version: 2 + +updates: + - package-ecosystem: npm + directory: / + schedule: + interval: weekly + day: monday + open-pull-requests-limit: 5 + groups: + dev-dependencies: + dependency-type: development + update-types: + - minor + - patch + production-dependencies: + dependency-type: production + update-types: + - minor + - patch + commit-message: + prefix: "deps" + include: scope + + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + day: monday + groups: + actions: + patterns: + - "*" + commit-message: + prefix: "ci" diff --git a/.github/workflows/build-sigplot.yml b/.github/workflows/build-sigplot.yml index 371bc6e..d3b98cb 100644 --- a/.github/workflows/build-sigplot.yml +++ b/.github/workflows/build-sigplot.yml @@ -1,53 +1,66 @@ -name: Build +name: CI on: push: - branches: [ master, develop ] + branches: [main, master, develop] tags: - - '*' + - "*" pull_request: - branches: [ master, develop ] + branches: [main, master, develop] jobs: - build: + lint: runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [12.x, 14.x, 16.x] - steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + - run: npm ci + - run: npm run lint -- --max-warnings=999 + - run: npm run format:check || echo "::warning::Formatting issues found. Run 'npm run format' to fix." - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v2 - with: - node-version: ${{ matrix.node-version }} - cache: 'npm' + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + - run: npm ci + - run: npm run build + - uses: actions/upload-artifact@v4 + with: + name: dist + path: dist/ - - name: Install dependencies - run: npm install -q + test: + runs-on: ubuntu-latest + needs: build + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + - run: npm ci + - run: npm run test - - name: Build SigPlot - run: npx grunt dist - publish: - needs: build + needs: [lint, build, test] if: startsWith(github.ref, 'refs/tags') runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - uses: actions/setup-node@v2 - with: - node-version: 12 - cache: 'npm' - - - run: npm install - - run: npm run build - - uses: JS-DevTools/npm-publish@v1 - with: - token: ${{ secrets.NPM_TOKEN }} - - if: steps.publish.outputs.type != 'none' - run: | - echo "Version changed: ${{ steps.publish.outputs.old-version }} => ${{ steps.publish.outputs.version }}" + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + registry-url: https://registry.npmjs.org + - run: npm ci + - run: npm run build + - run: npm publish + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.gitignore b/.gitignore index 8c339c4..5c7e4f8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,120 +1,34 @@ -*.o -*.so -*.exe +# Dependencies +node_modules/ + +# Build output +dist/ +dist/types/ + +# Generated docs +doc/ + +# OS files .DS_Store *~ -*.gitignore -Git_History -node_modules -/C:\nppdf32Log\debuglog.txt -.DS_Store -doc/ + +# Editor files .idea/ +*.swp +.vscode/ # Logs -logs *.log npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# Diagnostic reports (https://nodejs.org/api/report.html) -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json - -# Runtime data -pids -*.pid -*.seed -*.pid.lock -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov +# Coverage +coverage/ +.nyc_output/ -# Coverage directory used by tools like istanbul -coverage -*.lcov - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ - -# TypeScript cache -*.tsbuildinfo - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Microbundle cache -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file +# Environment .env .env.test -# parcel-bundler cache (https://parceljs.org/) -.cache - -# Next.js build output -.next - -# Nuxt.js build / generate output -.nuxt -dist - -# Gatsby files -.cache/ -# Comment in the public line in if your project uses Gatsby and *not* Next.js -# https://nextjs.org/blog/next-9-1#public-directory-support -# public - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# TernJS port file -.tern-port - -# Vim Swap Files -*.swp +# IDE caches +.eslintcache +*.tsbuildinfo diff --git a/.jsbeautifyrc b/.jsbeautifyrc deleted file mode 100644 index 0809af6..0000000 --- a/.jsbeautifyrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "indentSize": 4, - "indentWithTabs": false, - "wrapLineLength": 0, - "eol": "\n" -} diff --git a/.jsdoc.json b/.jsdoc.json deleted file mode 100644 index 34236ed..0000000 --- a/.jsdoc.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "tags": { - "allowUnknownTags": true, - "dictionaries": ["jsdoc"] - }, - "source": { - "include": ["js", "package.json", "README.md"], - "includePattern": ".js$", - "excludePattern": "(node_modules/|doc)" - }, - "plugins": [ - "plugins/markdown" - ], - "opts": { - "destination": "./doc", - "encoding": "utf8", - "private": true, - "recurse": true, - "template": "./node_modules/minami" - } -} diff --git a/.jshintignore b/.jshintignore deleted file mode 100644 index ffc6211..0000000 --- a/.jshintignore +++ /dev/null @@ -1,6 +0,0 @@ -js/typedarray.js -js/CanvasInput.js -js/spin.js -js/tinycolor.js -js/loglevel.js -js/slider.js diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 8c86fc7..0000000 --- a/.jshintrc +++ /dev/null @@ -1,14 +0,0 @@ -{ - "curly": true, - "eqeqeq": true, - "immed": true, - "latedef": true, - "newcap": true, - "noarg": true, - "sub": true, - "undef": true, - "unused": true, - "boss": true, - "eqnull": true, - "node": true -} diff --git a/.npmignore b/.npmignore deleted file mode 100644 index e69de29..0000000 diff --git a/.nvmrc b/.nvmrc deleted file mode 100644 index 2bf5ad0..0000000 --- a/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -stable diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 6d82eb4..0000000 --- a/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -language: node_js -node_js: - - "10.15.1" - -services: - - docker - -before_install: - - rm -rf dist/* - - npm install -g grunt - - npm install -q -script: - - grunt dist - -notifications: - email: - on_success: never - diff --git a/Gruntfile.js b/Gruntfile.js deleted file mode 100644 index 69d5292..0000000 --- a/Gruntfile.js +++ /dev/null @@ -1,276 +0,0 @@ -'use strict'; - -module.exports = function (grunt) { - - // Project configuration. - grunt.initConfig({ - // Metadata. - pkg: grunt.file.readJSON('package.json'), - jshint: { - options: { - jshintrc: '.jshintrc' - }, - gruntfile: { - src: 'Gruntfile.js' - }, - js: { - options: { - jshintrc: 'js/.jshintrc' - }, - src: ['js/**/*.js', 'test/tests*.js'] - }, - }, - qunit: { - options: { '--web-security': 'no', '--local-to-remote-url-access': 'yes' }, - all: ['test/test_headless.html'] - }, - 'closure-compiler': { - sigplot_debug: { - closurePath: 'support/google-closure-compiler', - js: 'dist/sigplot.js', - maxBuffer: 500, - jsOutputFile: 'dist/sigplot-debug.js', - options: { - formatting: 'PRETTY_PRINT', - compilation_level: 'WHITESPACE_ONLY', - } - }, - sigplot_plugins_debug: { - closurePath: 'support/google-closure-compiler', - js: 'dist/sigplot.plugins.js', - maxBuffer: 500, - jsOutputFile: 'dist/sigplot.plugins-debug.js', - options: { - formatting: 'PRETTY_PRINT', - compilation_level: 'WHITESPACE_ONLY' - } - }, - sigplot_minimized: { - closurePath: 'support/google-closure-compiler', - js: 'dist/sigplot.js', - maxBuffer: 500, - jsOutputFile: 'dist/sigplot-minimized.js', - options: { - compilation_level: 'SIMPLE_OPTIMIZATIONS' - } - }, - sigplot_plugins_minimized: { - closurePath: 'support/google-closure-compiler', - js: 'dist/sigplot.plugins.js', - maxBuffer: 500, - jsOutputFile: 'dist/sigplot.plugins-minimized.js', - options: { - compilation_level: 'SIMPLE_OPTIMIZATIONS' - } - } - }, - jsdoc: { - sigplot: { - src: ['js/*.js'], - options: { - destination: 'doc', - template: './node_modules/minami/', - configure: '.jsdoc.json' - } - } - }, - clean: { - build: ["dist/**/*", "!dist/*.zip"], - doc: ["doc/**/*"] - }, - compress: { - main: { - options: { - archive: "dist/sigplot-<%= pkg.version %>-<%= grunt.template.today('yyyy-mm-dd') %>.zip", - }, - files: [ - {expand: true, cwd: 'dist/', src: ['*-debug.js'], dest: 'sigplot-<%= pkg.version %>'}, - {expand: true, cwd: 'dist/', src: ['*-minimized.js'], dest: 'sigplot-<%= pkg.version %>'}, - {src: ['doc/**/*'], dest: 'sigplot-<%= pkg.version %>'} - ] - } - }, - githash: { - main: { - options: {} - } - }, - replace: { - version: { - src: ["dist/*.js"], - overwrite: true, - replacements: [{ - from: /version-PLACEHOLDER/g, - to: "<%= pkg.version %>-<%= githash.main.short %>", - }], - } - }, - 'http-server': { - 'test': { - cache: 0, - port: 1337 - }, - }, - jsbeautifier: { - check: { - // Only check a subset of the files - src: [ - 'js/m.js', - 'js/mx.js', - 'js/sigplot.layer1d.js', - 'js/sigplot.layer2d.js', - 'js/sigplot.js', - 'js/sigplot.annotations.js', - 'js/sigplot.slider.js', - 'js/sigplot.accordion.js', - 'js/sigplot.boxes.js', - 'js/sigplot.playback.js', - 'js/sigplot.plugin.js', - 'test/tests.js', - 'test/tests.colormap.js', - 'test/tests.interactive-accordion.js', - 'test/tests.interactive-appearance.js', - 'test/tests.interactive-boxes.js', - 'test/tests.interactive-core.js', - 'test/tests.interactive-cuts.js', - 'test/tests.interactive-layer1d.js', - 'test/tests.interactive-layer2d.js', - 'test/tests.interactive-menu.js', - 'test/tests.interactive-mouse.js', - 'test/tests.interactive-slider.js', - 'test/tests.interactive-symbols.js', - 'test/tests.m.js', - 'test/tests.mx.js', - 'test/tests.sigplot.js' - ], - options: { - mode: "VERIFY_ONLY", - config: ".jsbeautifyrc" - } - }, - cleanup: { - // Only cleanup a subset of the files - src: [ - 'js/m.js', - 'js/mx.js', - 'js/sigplot.layer1d.js', - 'js/sigplot.layer2d.js', - 'js/sigplot.js', - 'js/sigplot.annotations.js', - 'js/sigplot.slider.js', - 'js/sigplot.accordion.js', - 'js/sigplot.boxes.js', - 'js/sigplot.playback.js', - 'js/sigplot.plugin.js', - 'test/tests.js', - 'test/tests.colormap.js', - 'test/tests.interactive-accordion.js', - 'test/tests.interactive-appearance.js', - 'test/tests.interactive-boxes.js', - 'test/tests.interactive-core.js', - 'test/tests.interactive-cuts.js', - 'test/tests.interactive-layer1d.js', - 'test/tests.interactive-layer2d.js', - 'test/tests.interactive-menu.js', - 'test/tests.interactive-mouse.js', - 'test/tests.interactive-slider.js', - 'test/tests.interactive-symbols.js', - 'test/tests.m.js', - 'test/tests.mx.js', - 'test/tests.sigplot.js' - ], - options: { - config: ".jsbeautifyrc" - } - } - }, - express: { - test: { - options: { - script: 'benchmark/express.js' - } - } - }, - karma: { - bench: { - configFile: 'karma.conf.js' - } - }, - browserify: { - sigplot: { - src: 'js/sigplot.js', - dest: 'dist/sigplot.js', - options: { - browserifyOptions: { - standalone: 'sigplot', - debug: true - }, - transform: [ - [ - 'babelify', { - "presets": ["@babel/preset-env"] - } - ] - ] - } - }, - plugins: { - src: [ 'js/plugins.js' ], - dest: 'dist/sigplot.plugins.js', - options: { - browserifyOptions: { - standalone: 'sigplot_plugins', - debug: true - }, - transform: [ - [ - 'babelify', { - "presets": ["@babel/preset-env"] - } - ] - ] - } - } - } - }); - - // These plugins provide necessary tasks. - grunt.loadNpmTasks('grunt-closure-compiler'); - grunt.loadNpmTasks('grunt-contrib-jshint'); - grunt.loadNpmTasks('grunt-contrib-qunit'); - grunt.loadNpmTasks('grunt-jsdoc'); - grunt.loadNpmTasks('grunt-contrib-clean'); - grunt.loadNpmTasks('grunt-contrib-compress'); - grunt.loadNpmTasks('grunt-http-server'); - grunt.loadNpmTasks('grunt-jsbeautifier'); - grunt.loadNpmTasks('grunt-karma'); - grunt.loadNpmTasks('grunt-express-server'); - grunt.loadNpmTasks('grunt-browserify'); - grunt.loadNpmTasks('grunt-text-replace'); - grunt.loadNpmTasks('grunt-githash'); - - grunt.registerTask('build', ['jsbeautifier:check', 'jshint', 'browserify', 'githash', 'replace']); - - // Check everything is good - grunt.registerTask('test', ['build', 'qunit']); - - // Beautify the code - grunt.registerTask('prep', ['jsbeautifier:cleanup']); - - // Generate documentation - grunt.registerTask('generate-docs', ['jsdoc']); - - // Build a distributable release - grunt.registerTask('dist', ['clean', 'test', 'closure-compiler', 'jsdoc', 'compress']); - - // Default task. - grunt.registerTask('default', 'test'); - - // Benchmark in browsers. - grunt.registerTask('benchtest', ['express:test', 'karma:bench']); - grunt.registerTask('build_and_test', ['build', 'benchtest']); - - // for compatibility with the old grunt commands - grunt.registerTask('web_server', 'http-server'); - -}; diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..11113f4 --- /dev/null +++ b/biome.json @@ -0,0 +1,92 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.4.8/schema.json", + "files": { + "includes": [ + "**", + "!**/node_modules/", + "!**/dist/", + "!**/doc/", + "!**/benchmark/", + "!**/support/", + "!**/*.min.js", + "!**/coverage/" + ] + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 4, + "lineWidth": 120, + "lineEnding": "lf" + }, + "javascript": { + "formatter": { + "semicolons": "always", + "quoteStyle": "double", + "trailingCommas": "none", + "bracketSpacing": true, + "arrowParentheses": "always" + } + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "suspicious": { + "noDoubleEquals": "warn", + "noFallthroughSwitchClause": "warn", + "noRedeclare": "warn", + "noPrototypeBuiltins": "off", + "noAssignInExpressions": "off", + "noFunctionAssign": "warn", + "noVar": "off", + "noExplicitAny": "off", + "noImplicitAnyLet": "off", + "noConfusingVoidType": "off", + "noApproximativeNumericConstant": "off" + }, + "correctness": { + "noUnusedVariables": "warn", + "noUnusedImports": "warn", + "noSelfAssign": "warn", + "noInnerDeclarations": "off", + "noInvalidUseBeforeDeclaration": "off", + "noUnusedFunctionParameters": "off", + "noVoidTypeReturn": "warn", + "noConstructorReturn": "warn", + "noSwitchDeclarations": "warn" + }, + "style": { + "useConst": "off", + "noUselessElse": "off", + "useDefaultParameterLast": "off", + "noParameterAssign": "off", + "noNonNullAssertion": "off", + "useTemplate": "off", + "useExponentiationOperator": "off" + }, + "complexity": { + "noUselessConstructor": "off", + "noForEach": "off", + "noUselessSwitchCase": "off", + "useArrowFunction": "off", + "useLiteralKeys": "off", + "noUselessThisAlias": "off", + "noBannedTypes": "off", + "useDateNow": "off" + } + } + }, + "overrides": [ + { + "includes": ["test/**"], + "linter": { + "rules": { + "correctness": { + "noUnusedVariables": "off" + } + } + } + } + ] +} diff --git a/dist/.gitignore b/dist/.gitignore deleted file mode 100644 index f1a9653..0000000 --- a/dist/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.js.report.txt -*.js diff --git a/dist/.npmignore b/dist/.npmignore deleted file mode 100644 index 50543e5..0000000 --- a/dist/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -*.js.report.txt -*.zip diff --git a/esbuild.config.mjs b/esbuild.config.mjs new file mode 100644 index 0000000..5904ed3 --- /dev/null +++ b/esbuild.config.mjs @@ -0,0 +1,57 @@ +import * as esbuild from "esbuild"; + +const common = { + bundle: true, + target: "es2018", + sourcemap: true, + logLevel: "info", +}; + +// UMD-style bundle (IIFE with global name) — replaces browserify --standalone +await esbuild.build({ + ...common, + entryPoints: ["js/sigplot.ts"], + format: "iife", + globalName: "sigplot", + outfile: "dist/sigplot.js", + footer: { js: "sigplot = sigplot.default || sigplot;" }, +}); + +// Minified UMD +await esbuild.build({ + ...common, + entryPoints: ["js/sigplot.ts"], + format: "iife", + globalName: "sigplot", + outfile: "dist/sigplot.min.js", + minify: true, + footer: { js: "sigplot = sigplot.default || sigplot;" }, +}); + +// ESM bundle for modern consumers +await esbuild.build({ + ...common, + entryPoints: ["js/sigplot.ts"], + format: "esm", + outfile: "dist/sigplot.esm.js", + target: "es2020", +}); + +// Plugins bundle +await esbuild.build({ + ...common, + entryPoints: ["js/plugins.ts"], + format: "iife", + globalName: "sigplot_plugins", + outfile: "dist/sigplot.plugins.js", +}); + +// Plugins minified +await esbuild.build({ + ...common, + entryPoints: ["js/plugins.ts"], + format: "iife", + globalName: "sigplot_plugins", + outfile: "dist/sigplot.plugins.min.js", + minify: true, +}); diff --git a/examples/index.html b/examples/index.html index 490f218..4d06b9f 100644 --- a/examples/index.html +++ b/examples/index.html @@ -4,10 +4,10 @@