@nocturnium/svelte-ide 1.0.5 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -83,9 +83,11 @@
83
83
  * Get the color based on score level
84
84
  */
85
85
  function getColor(score: number): string {
86
- if (score >= 85) return '#ef4444'; // Critical - red
87
- if (score >= 70) return '#f59e0b'; // High - orange
88
- return '#3b82f6'; // Medium - blue
86
+ // Bands match the analyzer's levels: critical >= 85, high >= 70,
87
+ // medium otherwise (lines below the minScore threshold aren't shown).
88
+ if (score >= 85) return 'var(--ide-error)'; // Critical
89
+ if (score >= 70) return 'var(--ide-warning)'; // High
90
+ return 'var(--ide-info)'; // Medium
89
91
  }
90
92
 
91
93
  /**
@@ -26,7 +26,7 @@
26
26
  import CommandPalette from './CommandPalette.svelte';
27
27
  import { getComplexityAnalyzer, type ComplexityMetrics } from './core/complexity-analyzer';
28
28
  import { registerSemanticFoldCommands } from './core/commands';
29
- import { getSemanticAnalyzer } from './core/semantic-analyzer';
29
+ import { getSemanticAnalyzer, type FoldPreset } from './core/semantic-analyzer';
30
30
  import type { AIAwareness } from './core/ai-awareness';
31
31
  import {
32
32
  CURSOR_BLINK_MS,
@@ -501,6 +501,38 @@
501
501
  }
502
502
  }
503
503
 
504
+ /**
505
+ * Collapse every semantic region whose category is listed in `preset.hide`,
506
+ * after first expanding everything so presets compose predictably. Shared by
507
+ * the command-palette preset commands and the exported imperative API.
508
+ */
509
+ function applyFoldPresetInternal(preset: FoldPreset) {
510
+ if (!folding || !editorState) return;
511
+ foldManager.expandAll();
512
+ const analyzer = getSemanticAnalyzer();
513
+ const regions = analyzer.analyze(editorState.lines, language);
514
+ for (const category of preset.hide) {
515
+ for (const region of analyzer.getByCategory(regions, category)) {
516
+ foldManager.collapse(region.startLine);
517
+ }
518
+ }
519
+ }
520
+
521
+ /**
522
+ * Imperative API (accessible via `bind:this`): apply a semantic fold preset.
523
+ */
524
+ export function applyFoldPreset(preset: FoldPreset) {
525
+ applyFoldPresetInternal(preset);
526
+ }
527
+
528
+ /**
529
+ * Imperative API (accessible via `bind:this`): expand all folded regions.
530
+ */
531
+ export function unfoldAll() {
532
+ if (!folding || !editorState) return;
533
+ foldManager.expandAll();
534
+ }
535
+
504
536
  function handleFoldIndicatorClick(lineNumber: number, e: MouseEvent) {
505
537
  e.preventDefault();
506
538
  e.stopPropagation();
@@ -787,17 +819,7 @@
787
819
  foldManager?.expandAll();
788
820
  },
789
821
  onApplyPreset: (preset) => {
790
- // First expand all
791
- foldManager?.expandAll();
792
- // Then collapse categories that should be hidden
793
- const analyzer = getSemanticAnalyzer();
794
- const regions = analyzer.analyze(editorState.lines, language);
795
- for (const category of preset.hide) {
796
- const categoryRegions = analyzer.getByCategory(regions, category);
797
- for (const region of categoryRegions) {
798
- foldManager?.collapse(region.startLine);
799
- }
800
- }
822
+ applyFoldPresetInternal(preset);
801
823
  },
802
824
  getLanguage: () => language
803
825
  });
@@ -1,6 +1,7 @@
1
1
  import type { EditorPreferences } from '../../types';
2
2
  import { type Cursor } from './core';
3
3
  import { type ComplexityMetrics } from './core/complexity-analyzer';
4
+ import { type FoldPreset } from './core/semantic-analyzer';
4
5
  import type { AIAwareness } from './core/ai-awareness';
5
6
  interface Props {
6
7
  content: string;
@@ -32,6 +33,9 @@ interface Props {
32
33
  onComplexityChange?: (metrics: ComplexityMetrics | null) => void;
33
34
  onSave?: () => void;
34
35
  }
35
- declare const CustomEditor: import("svelte").Component<Props, {}, "content">;
36
+ declare const CustomEditor: import("svelte").Component<Props, {
37
+ applyFoldPreset: (preset: FoldPreset) => void;
38
+ unfoldAll: () => void;
39
+ }, "content">;
36
40
  type CustomEditor = ReturnType<typeof CustomEditor>;
37
41
  export default CustomEditor;
@@ -19,7 +19,11 @@ const THRESHOLDS = {
19
19
  * Weights for different complexity factors
20
20
  */
21
21
  const WEIGHTS = {
22
- nestingDepth: 15,
22
+ // Nesting is the dominant cognitive-load factor, but 15/level over-rated
23
+ // shallow code: a function with two nested `if`s landed at ~71 ("High").
24
+ // 12/level keeps deeply-nested code critical while letting genuinely medium
25
+ // code read as medium.
26
+ nestingDepth: 12,
23
27
  branchingFactor: 8,
24
28
  lineCount: 0.3,
25
29
  identifierCount: 0.2,
@@ -77,12 +81,15 @@ export class ComplexityAnalyzer {
77
81
  * Get complexity for a specific line
78
82
  */
79
83
  getLineComplexity(metrics, line) {
84
+ // A line can sit inside several nested regions; report the highest score
85
+ // so an inner low-complexity region never masks the hot function around it.
86
+ let best = 0;
80
87
  for (const region of metrics.regions) {
81
- if (line >= region.startLine && line <= region.endLine) {
82
- return region.score;
88
+ if (line >= region.startLine && line <= region.endLine && region.score > best) {
89
+ best = region.score;
83
90
  }
84
91
  }
85
- return 0;
92
+ return best;
86
93
  }
87
94
  /**
88
95
  * Check if a line is a hotspot
@@ -234,6 +241,20 @@ export class ComplexityAnalyzer {
234
241
  */
235
242
  getDefinitionCandidate(text, funcMatch, allowMethodStyle) {
236
243
  if (funcMatch) {
244
+ // The arrow-assignment branch (`name = (`) also matches a parenthesised
245
+ // expression like `const x = (a - b) / c`, which is NOT a function.
246
+ // Only treat it as one when the line actually starts an arrow: it
247
+ // contains `=>`, or it has an unclosed `(` that opens a multi-line arrow
248
+ // signature. Otherwise the stale candidate gets attached to the next
249
+ // `if (...) {` block and a phantom region is reported.
250
+ const isArrowAssignment = !!funcMatch[3] && !funcMatch[2] && !funcMatch[4] && !funcMatch[5];
251
+ if (isArrowAssignment) {
252
+ const opens = (text.match(/\(/g) || []).length;
253
+ const closes = (text.match(/\)/g) || []).length;
254
+ if (!text.includes('=>') && opens <= closes) {
255
+ return undefined;
256
+ }
257
+ }
237
258
  return {
238
259
  type: funcMatch[5] ? 'class' : 'function',
239
260
  name: funcMatch[2] || funcMatch[3] || funcMatch[4] || funcMatch[5]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocturnium/svelte-ide",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "Svelte 5 code editor and IDE building blocks — custom editor, syntax highlighting, code folding, multi-cursor, LSP client, and optional realtime collaboration.",
5
5
  "author": "Nocturnium & Jordan Dziat <hello@nocturnium.ai> (https://nocturnium.ai)",
6
6
  "license": "MIT",