diff --git a/refl1d/webview/client/.gitignore b/refl1d/webview/client/.gitignore new file mode 100644 index 00000000..1fed572a --- /dev/null +++ b/refl1d/webview/client/.gitignore @@ -0,0 +1,5 @@ +bumps-webview-client*.tgz +refl1d-webview-client*.tgz +bun.lock +dist/ +node_modules/ diff --git a/refl1d/webview/client/biome.json b/refl1d/webview/client/biome.json new file mode 100644 index 00000000..b251b17d --- /dev/null +++ b/refl1d/webview/client/biome.json @@ -0,0 +1,38 @@ +{ + "$schema": "./node_modules/@biomejs/biome/configuration_schema.json", + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + }, + "files": { + "ignoreUnknown": false, + "includes": ["**", "!**/*.css", "!**/*.scss"] + }, + "formatter": { + "enabled": true, + "formatWithErrors": false, + "indentStyle": "space", + "indentWidth": 2, + "lineEnding": "lf", + "lineWidth": 120, + "attributePosition": "auto", + "bracketSameLine": false, + "bracketSpacing": true, + "expand": "auto", + "useEditorconfig": true + }, + "linter": { + "enabled": true, + "domains": { + "vue": "recommended" + }, + "rules": { + "recommended": true + } + }, + "assist": { + "enabled": true, + "actions": { "source": { "organizeImports": "on" } } + } +} diff --git a/refl1d/webview/client/eslint.config.js b/refl1d/webview/client/eslint.config.js index 5e5d8e79..1f853bd1 100644 --- a/refl1d/webview/client/eslint.config.js +++ b/refl1d/webview/client/eslint.config.js @@ -1,10 +1,8 @@ -import url from "url"; -import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended"; -import pluginVue from "eslint-plugin-vue"; +import url from "node:url"; import { FlatCompat } from "@eslint/eslintrc"; import js from "@eslint/js"; -import prettierConfig from "@vue/eslint-config-prettier"; import vueTsEslintConfig from "@vue/eslint-config-typescript"; +import pluginVue from "eslint-plugin-vue"; const __dirname = url.fileURLToPath(new URL(".", import.meta.url)); const compat = new FlatCompat({ @@ -15,11 +13,9 @@ const compat = new FlatCompat({ export default [ /** Extend recommended configs */ - ...compat.extends("plugin:vue/vue3-recommended", "plugin:vuejs-accessibility/recommended", "prettier"), + ...compat.extends("plugin:vue/recommended", "plugin:vuejs-accessibility/recommended"), ...pluginVue.configs["flat/recommended"], ...vueTsEslintConfig(), - eslintPluginPrettierRecommended, - prettierConfig, /** Configuration */ { languageOptions: { @@ -39,13 +35,6 @@ export default [ "error", { allowShortCircuit: true, allowTernary: true }, // Temporary fix for indirect dependency @typescript-eslint <= 8.15.0 ], - "prettier/prettier": [ - "warn", - {}, - { - usePrettierrc: true, - }, - ], "vuejs-accessibility/label-has-for": [ "error", { @@ -54,6 +43,23 @@ export default [ }, }, ], + "vue/max-attributes-per-line": [ + "error", + { + singleline: { + max: 5, + }, + }, + ], + "vue/html-self-closing": [ + "error", + { + html: { + void: "any", + normal: "any", + }, + }, + ], }, }, ]; diff --git a/refl1d/webview/client/package.json b/refl1d/webview/client/package.json index 4c34c141..925fb499 100644 --- a/refl1d/webview/client/package.json +++ b/refl1d/webview/client/package.json @@ -1,6 +1,6 @@ { "name": "refl1d-webview-client", - "version": "0.1.26", + "version": "0.1.27", "type": "module", "repository": { "type": "git", @@ -12,44 +12,37 @@ "build": "vite build --emptyOutDir -m development", "build_prod": "vite build --emptyOutDir -m production", "preview": "vite preview --port 4173", - "format": "prettier --write src", + "format": "biome format --write", "lint": "eslint src --fix", "test:lint": "eslint src", "test:types": "vue-tsc --noEmit --skipLibCheck -p tsconfig.json --composite false" }, "dependencies": { "@msgpack/msgpack": "^3.1.2", - "bootstrap": "^5.3.7", + "bootstrap": "^5.3.8", "date-fns": "^4.1.0", "json-difference": "^1.16.1", - "mpld3": "^0.5.10", - "plotly.js": "^3.0.1", + "mpld3": "^0.5.12", + "plotly.js": "^3.3.0", "socket.io-client": "^4.8.1", - "uuid": "^11.1.0", - "vue": "^3.5.17", - "vue-json-pretty": "^2.5.0" + "uuid": "^13.0.0", + "vue": "^3.5.25", + "vue-json-pretty": "^2.6.0" }, "devDependencies": { - "@ianvs/prettier-plugin-sort-imports": "^4.4.1", - "@tsconfig/node-lts": "^22.0.2", - "@types/node": "^24.5.2", - "@types/plotly.js": "^2.35.1", - "@types/uuid": "^10.0.0", - "@vitejs/plugin-vue": "^5.2.1", - "@vue/eslint-config-prettier": "10.1.0", - "@vue/eslint-config-typescript": "^14.2.0", - "@vue/tsconfig": "^0.7.0", - "eslint": "^9.18.0", - "eslint-config-prettier": "^10.0.1", - "eslint-plugin-prettier": "^5.2.1", - "eslint-plugin-vue": "^9.32.0", + "@tsconfig/node-lts": "^24.0.0", + "@types/node": "^24.10.1", + "@types/plotly.js": "^3.0.8", + "@vitejs/plugin-vue": "^6.0.2", + "@vue/eslint-config-typescript": "^14.6.0", + "@vue/tsconfig": "^0.8.1", + "@biomejs/biome": "^2.3.8", + "eslint": "^9.39.1", + "eslint-plugin-vue": "^10.6.2", "eslint-plugin-vuejs-accessibility": "^2.4.1", - "prettier": "^3.4.2", - "prettier-plugin-css-order": "^2.1.2", - "prettier-plugin-jsdoc": "^1.3.2", - "typescript": "^5.7.3", - "vite": "^6.0.7", + "typescript": "^5.9.3", + "vite": "^7.2.6", "vite-svg-loader": "5.1.0", - "vue-tsc": "^2.2.0" + "vue-tsc": "^3.1.5" } } diff --git a/refl1d/webview/client/src/components/DataView.vue b/refl1d/webview/client/src/components/DataView.vue index f9c637eb..395ca12e 100644 --- a/refl1d/webview/client/src/components/DataView.vue +++ b/refl1d/webview/client/src/components/DataView.vue @@ -68,15 +68,13 @@ function generate_new_traces(model_data: ModelData[][], view: ReflectivityPlot, const local_offset = lin_y ? plot_index * offset : Math.pow(10, plot_index * offset); const background_offset = apply_corrections.value ? xs.background : 0.0; const intensity_scale = apply_corrections.value ? xs.intensity : 1.0; - const y = - lin_y ? - xs.theory.map((t) => (t - background_offset) / intensity_scale + local_offset) + const y = lin_y + ? xs.theory.map((t) => (t - background_offset) / intensity_scale + local_offset) : xs.theory.map((t) => ((t - background_offset) / intensity_scale) * local_offset); theory_traces.push({ x: xs.Q, y: y, mode: "lines", name: label + " theory", line: { width: 2, color } }); if (xs.R !== undefined) { - const R = - lin_y ? - xs.R.map((t) => (t - background_offset) / intensity_scale + local_offset) + const R = lin_y + ? xs.R.map((t) => (t - background_offset) / intensity_scale + local_offset) : xs.R.map((t) => ((t - background_offset) / intensity_scale) * local_offset); const data_trace: Trace = { x: xs.Q, @@ -91,11 +89,12 @@ function generate_new_traces(model_data: ModelData[][], view: ReflectivityPlot, data_trace.error_x = { type: "data", array: xs.dQ, visible: true }; } if (xs.dR !== undefined) { - const dR = - lin_y ? xs.dR.map((t) => t / intensity_scale) : xs.dR.map((t) => (t / intensity_scale) * local_offset); + const dR = lin_y + ? xs.dR.map((t) => t / intensity_scale) + : xs.dR.map((t) => (t / intensity_scale) * local_offset); data_trace.error_y = { type: "data", array: dR, visible: true }; if (calculate_residuals) { - const residuals = xs.R.map((r, i) => (r - xs.theory[i]) / xs.dR![i]); + const residuals = xs.R.map((r, i) => (r - xs.theory[i]!) / xs.dR![i]!); const residuals_trace: Trace = { x: xs.Q, y: residuals, @@ -127,7 +126,7 @@ function generate_new_traces(model_data: ModelData[][], view: ReflectivityPlot, const lin_y = !log_y.value; const background_offset = apply_corrections.value ? xs.background : 0.0; const local_offset = lin_y ? plot_index * offset : Math.pow(10, plot_index * offset); - const theory = xs.theory.map((y, i) => (y - background_offset) / (xs.fresnel[i] - background_offset)); + const theory = xs.theory.map((y, i) => (y - background_offset) / (xs.fresnel![i]! - background_offset)); const offset_theory = lin_y ? theory.map((t) => t + local_offset) : theory.map((t) => t * local_offset); theory_traces.push({ x: xs.Q, @@ -137,7 +136,7 @@ function generate_new_traces(model_data: ModelData[][], view: ReflectivityPlot, line: { width: 2, color }, }); if (xs.R !== undefined) { - const R = xs.R.map((y, i) => (y - background_offset) / (xs.fresnel[i] - background_offset)); + const R = xs.R.map((y, i) => (y - background_offset) / (xs.fresnel![i]! - background_offset)); const offset_R = lin_y ? R.map((t) => t + local_offset) : R.map((t) => t * local_offset); const data_trace: Trace = { x: xs.Q, @@ -152,11 +151,11 @@ function generate_new_traces(model_data: ModelData[][], view: ReflectivityPlot, data_trace.error_x = { type: "data", array: xs.dQ, visible: true }; } if (xs.dR !== undefined) { - const dR = xs.dR.map((dy, i) => dy / (xs.fresnel[i] - background_offset)); + const dR = xs.dR.map((dy, i) => dy / (xs.fresnel![i]! - background_offset)); const dR_offset = lin_y ? dR : dR.map((t) => t * local_offset); data_trace.error_y = { type: "data", array: dR_offset, visible: true }; if (calculate_residuals) { - const residuals = xs.R.map((r, i) => (r - xs.theory[i]) / xs.dR![i]); + const residuals = xs.R.map((r, i) => (r - xs.theory[i]!) / xs.dR![i]!); const residuals_trace: Trace = { x: xs.Q, y: residuals, @@ -192,7 +191,7 @@ function generate_new_traces(model_data: ModelData[][], view: ReflectivityPlot, const intensity_scale = apply_corrections.value ? intensity : 1.0; const background_offset = apply_corrections.value ? background : 0.0; const Q4 = xs.Q.map((qq) => 1e-8 * Math.pow(qq, -4) * intensity_scale); - const theory = xs.theory.map((t, i) => (t - background_offset) / Q4[i]); + const theory = xs.theory.map((t, i) => (t - background_offset) / Q4![i]!); const offset_theory = theory.map((t) => t * local_offset); theory_traces.push({ x: xs.Q, @@ -202,7 +201,7 @@ function generate_new_traces(model_data: ModelData[][], view: ReflectivityPlot, line: { width: 2, color }, }); if (xs.R !== undefined) { - const R = xs.R.map((r, i) => (r - background_offset) / Q4[i]); + const R = xs.R.map((r, i) => (r - background_offset) / Q4![i]!); const offset_R = R.map((t) => t * local_offset); const data_trace: Trace = { x: xs.Q, @@ -217,11 +216,11 @@ function generate_new_traces(model_data: ModelData[][], view: ReflectivityPlot, data_trace.error_x = { type: "data", array: xs.dQ, visible: true }; } if (xs.dR !== undefined) { - const dR = xs.dR.map((dy, i) => dy / Q4[i]); + const dR = xs.dR.map((dy, i) => dy / Q4[i]!); const offset_dR = dR.map((t) => t * local_offset); data_trace.error_y = { type: "data", array: offset_dR, visible: true }; if (calculate_residuals) { - const residuals = xs.R.map((r, i) => (r - xs.theory[i]) / xs.dR![i]); + const residuals = xs.R.map((r, i) => (r - xs.theory[i]!) / xs.dR![i]!); const residuals_trace: Trace = { x: xs.Q, y: residuals, @@ -264,9 +263,9 @@ function generate_new_traces(model_data: ModelData[][], view: ReflectivityPlot, const legendgroup = `group_${plot_index}`; const Tm = interp(pp.Q, mm.Q, mm.theory); - const TSA = Tm.map((m, i) => { - const p_corr = (pp.theory[i] - pp_background_offset) / pp_intensity_scale; - const m_corr = (mm.theory[i] - mm_background_offset) / mm_intensity_scale; + const TSA = Tm.map((_m, i) => { + const p_corr = (pp.theory[i]! - pp_background_offset) / pp_intensity_scale; + const m_corr = (mm.theory[i]! - mm_background_offset) / mm_intensity_scale; return (p_corr - m_corr) / (p_corr + m_corr) + local_offset; }); @@ -277,7 +276,7 @@ function generate_new_traces(model_data: ModelData[][], view: ReflectivityPlot, const p_corr = pp.R.map((r) => (r - pp_background_offset) / pp_intensity_scale); const m_corr = Rm.map((r) => (r - mm_background_offset) / mm_intensity_scale); const SA = m_corr.map((m, i) => { - const p = p_corr[i]; + const p = p_corr[i]!; return (p - m) / (p + m); }); const SA_offset = SA.map((v) => v + local_offset); @@ -297,15 +296,15 @@ function generate_new_traces(model_data: ModelData[][], view: ReflectivityPlot, if (pp.dR !== undefined && mm.dR !== undefined) { const dRm = interp(pp.Q, mm.Q, mm.dR); const dSA = dRm.map((dm, i) => { - const dp_corr = pp.dR![i] / pp_intensity_scale; + const dp_corr = pp.dR![i]! / pp_intensity_scale; const dm_corr = dm / mm_intensity_scale; - const p = p_corr[i]; - const m = m_corr[i]; + const p = p_corr[i]!; + const m = m_corr[i]!; return Math.sqrt((4 * ((p * dm_corr) ** 2 + (m * dp_corr) ** 2)) / (p + m) ** 4); }); data_trace.error_y = { type: "data", array: dSA, visible: true }; if (calculate_residuals) { - const residuals = SA.map((v, i) => (v - TSA[i]) / dSA[i]); + const residuals = SA.map((v, i) => (v - TSA![i]!) / dSA[i]!); const residuals_trace: Trace = { x: pp.Q, y: residuals, @@ -362,7 +361,7 @@ async function draw_plot() { const { theory_traces, data_traces, xaxis_label, yaxis_label } = generate_new_traces( plot_data.value, reflectivity_type.value, - show_residuals.value + show_residuals.value, ); const layout: Partial = { uirevision: reflectivity_type.value, @@ -448,13 +447,17 @@ function interp(x: number[], xp: number[], fp: number[]): number[] { throw new Error(`lengths of xp (${xp.length}) and fp (${fp.length}) must match`); } + if (xp.length < 2) { + throw new Error("length of xp, fp must be > 1"); + } + const xpv = xp.values(); const fpv = fp.values(); - const lowest_xp = xp[0]; - const lowest_fp = fp[0]; + const lowest_xp = xp[0]!; + const lowest_fp = fp[0]!; // const highest_xp = xp[xp.length - 1]; - const highest_fp = fp[fp.length - 1]; + const highest_fp = fp[fp.length - 1]!; let lower_xp = xpv.next(); let lower_fp = fpv.next(); @@ -484,7 +487,7 @@ function interp(x: number[], xp: number[], fp: number[]): number[] { lower_fp.value! ); } - }); + }) as number[]; } @@ -545,8 +548,7 @@ function interp(x: number[], xp: number[], fp: number[]): number[] { for="apply_corrections" class="form-check-label" title="Apply background and intensity corrections to data instead of theory" - >Rcorr + >Rcorr
diff --git a/refl1d/webview/client/src/components/ModelView.vue b/refl1d/webview/client/src/components/ModelView.vue index 6c7bbcc2..72698db7 100644 --- a/refl1d/webview/client/src/components/ModelView.vue +++ b/refl1d/webview/client/src/components/ModelView.vue @@ -1,5 +1,4 @@