fix(frontend): resolve 26 svelte-check type errors
- add @types/node for hooks.server process/env types - fix katex auto-render import path (contrib/auto-render) - declare global Web Bluetooth API types in ble-deployer - guard simApi null in CircuitEditor autosave interval - default-type imports for CodeEditor/CircuitEditor - make lesson slug getter non-nullable - add expected_flowchart to LessonContent type - key lesson workspace by slug; drop phantom onReset prop - guard CodeTab render when lesson data is null
This commit is contained in:
parent
9ee92cfaaf
commit
c356e234fa
|
|
@ -21,6 +21,7 @@
|
|||
"@sveltejs/kit": "^2.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
||||
"@types/katex": "^0.16.7",
|
||||
"@types/node": "^26.2.0",
|
||||
"svelte": "^5.0.0",
|
||||
"svelte-check": "^4.0.0",
|
||||
"typescript": "^5.0.0",
|
||||
|
|
@ -1287,6 +1288,16 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "26.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-26.2.0.tgz",
|
||||
"integrity": "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~8.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/resolve": {
|
||||
"version": "1.20.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
|
||||
|
|
@ -2279,6 +2290,13 @@
|
|||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz",
|
||||
"integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "6.4.3",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.4.3.tgz",
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
"@sveltejs/kit": "^2.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
||||
"@types/katex": "^0.16.7",
|
||||
"@types/node": "^26.2.0",
|
||||
"svelte": "^5.0.0",
|
||||
"svelte-check": "^4.0.0",
|
||||
"typescript": "^5.0.0",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ export async function autoRenderMath(node: HTMLElement) {
|
|||
if (!browser) return;
|
||||
|
||||
try {
|
||||
const renderMathInElement = (await import('katex/dist/contrib/auto-render')).default;
|
||||
const renderMathInElement = (await import('katex/contrib/auto-render')).default;
|
||||
await import('katex/dist/katex.min.css');
|
||||
|
||||
// 1. First, handle the standard delimiters
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@
|
|||
$effect(() => {
|
||||
if (simApi && ready && storageKey) {
|
||||
const interval = setInterval(() => {
|
||||
if (!simApi) return;
|
||||
const currentText = simApi.exportCircuit();
|
||||
const saved = localStorage.getItem(storageKey);
|
||||
if (currentText && currentText !== saved && currentText.trim().length > 10) {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,98 @@ import {
|
|||
type DeployProgress, type BLEACKResponse
|
||||
} from '$types/deployer';
|
||||
|
||||
/* Ambient declarations for Web Bluetooth API (not in TS lib.dom.d.ts). */
|
||||
/* Minimal subset needed by BLEHardwareDeployer. */
|
||||
/* Wrapped in declare global because the file is a module (has imports) */
|
||||
/* and we need these types to be globally visible. */
|
||||
declare global {
|
||||
interface Navigator {
|
||||
readonly bluetooth: Bluetooth;
|
||||
}
|
||||
|
||||
interface Bluetooth {
|
||||
requestDevice(options: RequestDeviceOptions): Promise<BluetoothDevice>;
|
||||
}
|
||||
|
||||
interface RequestDeviceOptions {
|
||||
filters?: BluetoothLEScanFilter[];
|
||||
optionalServices?: BluetoothServiceUUID[];
|
||||
acceptAllDevices?: boolean;
|
||||
}
|
||||
|
||||
interface BluetoothLEScanFilter {
|
||||
name?: string;
|
||||
namePrefix?: string;
|
||||
services?: BluetoothServiceUUID[];
|
||||
manufacturerId?: number;
|
||||
}
|
||||
|
||||
type BluetoothServiceUUID = string | number;
|
||||
|
||||
interface BluetoothDevice {
|
||||
readonly id: string;
|
||||
readonly name?: string;
|
||||
readonly gatt?: BluetoothRemoteGATTServer;
|
||||
addEventListener(
|
||||
type: 'gattserverdisconnected',
|
||||
listener: (this: BluetoothDevice, ev: Event) => void
|
||||
): void;
|
||||
removeEventListener(
|
||||
type: 'gattserverdisconnected',
|
||||
listener: (this: BluetoothDevice, ev: Event) => void
|
||||
): void;
|
||||
}
|
||||
|
||||
interface BluetoothRemoteGATTServer {
|
||||
readonly connected: boolean;
|
||||
readonly device: BluetoothDevice;
|
||||
readonly mtu: number;
|
||||
connect(): Promise<BluetoothRemoteGATTServer>;
|
||||
disconnect(): void;
|
||||
requestMTU(size: number): Promise<BluetoothRemoteGATTServer>;
|
||||
getPrimaryService(service: BluetoothServiceUUID): Promise<BluetoothRemoteGATTService>;
|
||||
getPrimaryServices(service?: BluetoothServiceUUID): Promise<BluetoothRemoteGATTService[]>;
|
||||
}
|
||||
|
||||
interface BluetoothRemoteGATTService {
|
||||
readonly device: BluetoothDevice;
|
||||
readonly uuid: string;
|
||||
readonly isPrimary: boolean;
|
||||
getCharacteristic(characteristic: BluetoothServiceUUID): Promise<BluetoothRemoteGATTCharacteristic>;
|
||||
getCharacteristics(characteristic?: BluetoothServiceUUID): Promise<BluetoothRemoteGATTCharacteristic[]>;
|
||||
}
|
||||
|
||||
interface BluetoothRemoteGATTCharacteristic extends EventTarget {
|
||||
readonly service: BluetoothRemoteGATTService;
|
||||
readonly uuid: string;
|
||||
readonly properties: BluetoothCharacteristicProperties;
|
||||
readonly value: DataView | null;
|
||||
readValue(): Promise<DataView>;
|
||||
writeValue(value: BufferSource): Promise<void>;
|
||||
writeValueWithResponse(value: BufferSource): Promise<void>;
|
||||
writeValueWithoutResponse(value: BufferSource): Promise<void>;
|
||||
startNotifications(): Promise<BluetoothRemoteGATTCharacteristic>;
|
||||
stopNotifications(): Promise<BluetoothRemoteGATTCharacteristic>;
|
||||
addEventListener(
|
||||
type: 'characteristicvaluechanged',
|
||||
listener: (this: BluetoothRemoteGATTCharacteristic, ev: Event) => void
|
||||
): void;
|
||||
removeEventListener(
|
||||
type: 'characteristicvaluechanged',
|
||||
listener: (this: BluetoothRemoteGATTCharacteristic, ev: Event) => void
|
||||
): void;
|
||||
}
|
||||
|
||||
interface BluetoothCharacteristicProperties {
|
||||
readonly read: boolean;
|
||||
readonly write: boolean;
|
||||
readonly notify: boolean;
|
||||
readonly indicate: boolean;
|
||||
readonly writeWithoutResponse: boolean;
|
||||
readonly broadcast: boolean;
|
||||
}
|
||||
}
|
||||
|
||||
let _ackNotificationCount = 0;
|
||||
function logAck(tag: string, msg: string) {
|
||||
console.log(`[BLE-ACK#${++_ackNotificationCount}] ${tag}: ${msg}`);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ export interface LessonContent {
|
|||
initial_python: string;
|
||||
initial_circuit: string;
|
||||
initial_flowchart?: any;
|
||||
expected_flowchart?: string;
|
||||
initial_quiz: string;
|
||||
initial_code_arduino: string;
|
||||
velxio_circuit: string;
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ import QuizQuestionView from './QuizQuestionView.svelte';
|
|||
</svelte:head>
|
||||
|
||||
{#if pageData.lesson}
|
||||
{#key pageData.lesson.filename}
|
||||
{#key mgr.slug}
|
||||
<div class="lesson-layout" class:single-col={float.floating || mgr.isMobile}>
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<div class="lesson-content" bind:this={contentEl} use:noSelect use:renderMath
|
||||
|
|
@ -326,7 +326,6 @@ import QuizQuestionView from './QuizQuestionView.svelte';
|
|||
storageKey={mgr.flowchartStorageKey}
|
||||
initialData={mgr.data?.initial_flowchart}
|
||||
onRun={mgr.handleRun.bind(mgr)}
|
||||
onReset={mgr.handleReset.bind(mgr)}
|
||||
compiling={mgr.compiling}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -343,7 +342,7 @@ import QuizQuestionView from './QuizQuestionView.svelte';
|
|||
</div>
|
||||
{/if}
|
||||
|
||||
{#if !mgr.data?.active_tabs?.length || mgr.data.active_tabs.includes('c') || mgr.data.active_tabs.includes('python')}
|
||||
{#if mgr.data && (!mgr.data.active_tabs?.length || mgr.data.active_tabs.includes('c') || mgr.data.active_tabs.includes('python'))}
|
||||
<div class="tab-panel" class:tab-hidden={mgr.activeTab !== 'editor'}>
|
||||
<CodeTab
|
||||
data={mgr.data}
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ import { evaluateCircuitSubmission, processLanguageEvaluation } from '$services/
|
|||
import { getVelxioState, initVelxioBridge } from '$services/velxio-manager';
|
||||
import { VelxioBridge } from '$services/velxio-bridge';
|
||||
import type { LessonContent } from '$types/lesson';
|
||||
import type { CodeEditor } from '$components/CodeEditor.svelte';
|
||||
import type { CircuitEditor } from '$components/CircuitEditor.svelte';
|
||||
import type CodeEditor from '$components/CodeEditor.svelte';
|
||||
import type CircuitEditor from '$components/CircuitEditor.svelte';
|
||||
import type { DeployState } from '$types/deployer';
|
||||
import type { QuizQuestion, QuizAnswer } from '$types/quiz';
|
||||
import {
|
||||
|
|
@ -71,7 +71,7 @@ export class LessonManager {
|
|||
circuitEditor = $state<CircuitEditor | null>(null);
|
||||
flowchartTab = $state<any>(null);
|
||||
|
||||
get slug() { return get(page).params.slug; }
|
||||
get slug(): string { return get(page).params.slug ?? ''; }
|
||||
|
||||
isVelxio = $derived(this.data?.active_tabs?.includes('velxio') ?? false);
|
||||
isFlowchart = $derived(this.data?.active_tabs?.includes('flowchart') ?? false);
|
||||
|
|
@ -379,7 +379,7 @@ export class LessonManager {
|
|||
this.activeTab = 'output';
|
||||
try {
|
||||
const circuitText = this.circuitEditor.getCircuitText();
|
||||
const res = evaluateCircuitSubmission(simApi, circuitText, this.isHybrid, this.data, () => this.checkAllPassed());
|
||||
const res = evaluateCircuitSubmission(simApi, circuitText, this.isHybrid ?? false, this.data, () => this.checkAllPassed());
|
||||
if (res.error) {
|
||||
Object.assign(this.circuitOut, { error: res.error, success: false, loading: false });
|
||||
return;
|
||||
|
|
|
|||
Loading…
Reference in New Issue