@pyreon/code 0.11.5 → 0.11.7

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.
package/src/editor.ts CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  closeBrackets,
4
4
  closeBracketsKeymap,
5
5
  completionKeymap,
6
- } from "@codemirror/autocomplete"
6
+ } from '@codemirror/autocomplete'
7
7
  import {
8
8
  redo as cmRedo,
9
9
  undo as cmUndo,
@@ -11,7 +11,7 @@ import {
11
11
  history,
12
12
  historyKeymap,
13
13
  indentWithTab,
14
- } from "@codemirror/commands"
14
+ } from '@codemirror/commands'
15
15
  import {
16
16
  bracketMatching,
17
17
  defaultHighlightStyle,
@@ -20,10 +20,10 @@ import {
20
20
  indentOnInput,
21
21
  indentUnit,
22
22
  syntaxHighlighting,
23
- } from "@codemirror/language"
24
- import { setDiagnostics as cmSetDiagnostics, lintKeymap } from "@codemirror/lint"
25
- import { highlightSelectionMatches, searchKeymap } from "@codemirror/search"
26
- import { Compartment, EditorState, type Extension } from "@codemirror/state"
23
+ } from '@codemirror/language'
24
+ import { setDiagnostics as cmSetDiagnostics, lintKeymap } from '@codemirror/lint'
25
+ import { highlightSelectionMatches, searchKeymap } from '@codemirror/search'
26
+ import { Compartment, EditorState, type Extension } from '@codemirror/state'
27
27
  import {
28
28
  GutterMarker as CMGutterMarker,
29
29
  crosshairCursor,
@@ -41,12 +41,12 @@ import {
41
41
  rectangularSelection,
42
42
  ViewPlugin,
43
43
  type ViewUpdate,
44
- } from "@codemirror/view"
45
- import { computed, effect, signal } from "@pyreon/reactivity"
46
- import { loadLanguage } from "./languages"
47
- import { minimapExtension } from "./minimap"
48
- import { resolveTheme } from "./themes"
49
- import type { EditorConfig, EditorInstance, EditorLanguage, EditorTheme } from "./types"
44
+ } from '@codemirror/view'
45
+ import { computed, effect, signal } from '@pyreon/reactivity'
46
+ import { loadLanguage } from './languages'
47
+ import { minimapExtension } from './minimap'
48
+ import { resolveTheme } from './themes'
49
+ import type { EditorConfig, EditorInstance, EditorLanguage, EditorTheme } from './types'
50
50
 
51
51
  /**
52
52
  * Create a reactive code editor instance.
@@ -74,9 +74,9 @@ import type { EditorConfig, EditorInstance, EditorLanguage, EditorTheme } from "
74
74
  */
75
75
  export function createEditor(config: EditorConfig = {}): EditorInstance {
76
76
  const {
77
- value: initialValue = "",
78
- language: initialLanguage = "plain",
79
- theme: initialTheme = "light",
77
+ value: initialValue = '',
78
+ language: initialLanguage = 'plain',
79
+ theme: initialTheme = 'light',
80
80
  lineNumbers: showLineNumbers = true,
81
81
  readOnly: initialReadOnly = false,
82
82
  foldGutter: showFoldGutter = true,
@@ -128,7 +128,7 @@ export function createEditor(config: EditorConfig = {}): EditorInstance {
128
128
  const selection = computed(() => {
129
129
  docVersion()
130
130
  const v = view.peek()
131
- if (!v) return { from: 0, to: 0, text: "" }
131
+ if (!v) return { from: 0, to: 0, text: '' }
132
132
  const sel = v.state.selection.main
133
133
  return {
134
134
  from: sel.from,
@@ -140,7 +140,7 @@ export function createEditor(config: EditorConfig = {}): EditorInstance {
140
140
  const lineCount = computed(() => {
141
141
  docVersion()
142
142
  const v = view.peek()
143
- return v ? v.state.doc.lines : initialValue.split("\n").length
143
+ return v ? v.state.doc.lines : initialValue.split('\n').length
144
144
  })
145
145
 
146
146
  // ── Line highlight support ──────────────────────────────────────────
@@ -191,30 +191,30 @@ export function createEditor(config: EditorConfig = {}): EditorInstance {
191
191
 
192
192
  constructor(opts: { class?: string; text?: string; title?: string }) {
193
193
  super()
194
- this.markerText = opts.text ?? ""
195
- this.markerTitle = opts.title ?? ""
196
- this.markerClass = opts.class ?? ""
194
+ this.markerText = opts.text ?? ''
195
+ this.markerTitle = opts.title ?? ''
196
+ this.markerClass = opts.class ?? ''
197
197
  }
198
198
 
199
199
  override toDOM() {
200
- const el = document.createElement("span")
200
+ const el = document.createElement('span')
201
201
  el.textContent = this.markerText
202
202
  el.title = this.markerTitle
203
203
  if (this.markerClass) el.className = this.markerClass
204
- el.style.cssText = "cursor: pointer; display: inline-block; width: 100%; text-align: center;"
204
+ el.style.cssText = 'cursor: pointer; display: inline-block; width: 100%; text-align: center;'
205
205
  return el
206
206
  }
207
207
  }
208
208
 
209
209
  const gutterMarkerExtension = gutter({
210
- class: "pyreon-code-gutter-markers",
210
+ class: 'pyreon-code-gutter-markers',
211
211
  lineMarker: (gutterView, line) => {
212
212
  const lineNo = gutterView.state.doc.lineAt(line.from).number
213
213
  const marker = gutterMarkers.get(lineNo)
214
214
  if (!marker) return null
215
215
  return new CustomGutterMarker(marker)
216
216
  },
217
- initialSpacer: () => new CustomGutterMarker({ text: " " }),
217
+ initialSpacer: () => new CustomGutterMarker({ text: ' ' }),
218
218
  })
219
219
 
220
220
  // ── Build extensions ─────────────────────────────────────────────────
@@ -232,7 +232,7 @@ export function createEditor(config: EditorConfig = {}): EditorInstance {
232
232
  highlightSelectionMatches(),
233
233
  indentOnInput(),
234
234
  syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
235
- indentUnit.of(" ".repeat(configTabSize)),
235
+ indentUnit.of(' '.repeat(configTabSize)),
236
236
 
237
237
  // Keymaps
238
238
  keymap.of([
@@ -283,10 +283,10 @@ export function createEditor(config: EditorConfig = {}): EditorInstance {
283
283
  if (enableIndentGuides) {
284
284
  exts.push(
285
285
  EditorView.theme({
286
- ".cm-line": {
287
- backgroundImage: "linear-gradient(to right, #e5e7eb 1px, transparent 1px)",
286
+ '.cm-line': {
287
+ backgroundImage: 'linear-gradient(to right, #e5e7eb 1px, transparent 1px)',
288
288
  backgroundSize: `${configTabSize}ch 100%`,
289
- backgroundPosition: "0 0",
289
+ backgroundPosition: '0 0',
290
290
  },
291
291
  }),
292
292
  )
@@ -425,20 +425,20 @@ export function createEditor(config: EditorConfig = {}): EditorInstance {
425
425
  function foldAll(): void {
426
426
  const v = view.peek()
427
427
  if (!v) return
428
- const { foldAll: foldAllCmd } = require("@codemirror/language")
428
+ const { foldAll: foldAllCmd } = require('@codemirror/language')
429
429
  foldAllCmd(v)
430
430
  }
431
431
 
432
432
  function unfoldAll(): void {
433
433
  const v = view.peek()
434
434
  if (!v) return
435
- const { unfoldAll: unfoldAllCmd } = require("@codemirror/language")
435
+ const { unfoldAll: unfoldAllCmd } = require('@codemirror/language')
436
436
  unfoldAllCmd(v)
437
437
  }
438
438
 
439
439
  // ── Diagnostics ────────────────────────────────────────────────────
440
440
 
441
- function setDiagnostics(diagnostics: import("./types").Diagnostic[]): void {
441
+ function setDiagnostics(diagnostics: import('./types').Diagnostic[]): void {
442
442
  const v = view.peek()
443
443
  if (!v) return
444
444
  v.dispatch(
@@ -447,7 +447,7 @@ export function createEditor(config: EditorConfig = {}): EditorInstance {
447
447
  diagnostics.map((d) => ({
448
448
  from: d.from,
449
449
  to: d.to,
450
- severity: d.severity === "hint" ? "info" : d.severity,
450
+ severity: d.severity === 'hint' ? 'info' : d.severity,
451
451
  message: d.message,
452
452
  ...(d.source != null ? { source: d.source } : {}),
453
453
  })),
@@ -478,7 +478,7 @@ export function createEditor(config: EditorConfig = {}): EditorInstance {
478
478
 
479
479
  // ── Gutter markers ────────────────────────────────────────────────
480
480
 
481
- function setGutterMarker(line: number, marker: import("./types").GutterMarker): void {
481
+ function setGutterMarker(line: number, marker: import('./types').GutterMarker): void {
482
482
  gutterMarkers.set(line, marker)
483
483
  const v = view.peek()
484
484
  if (v) v.dispatch({ effects: [] })
@@ -513,14 +513,14 @@ export function createEditor(config: EditorConfig = {}): EditorInstance {
513
513
 
514
514
  function getLine(line: number): string {
515
515
  const v = view.peek()
516
- if (!v) return ""
516
+ if (!v) return ''
517
517
  const clamped = Math.min(Math.max(1, line), v.state.doc.lines)
518
518
  return v.state.doc.line(clamped).text
519
519
  }
520
520
 
521
521
  function getWordAtCursor(): string {
522
522
  const v = view.peek()
523
- if (!v) return ""
523
+ if (!v) return ''
524
524
  const pos = v.state.selection.main.head
525
525
  const line = v.state.doc.lineAt(pos)
526
526
  const col = pos - line.from
@@ -539,7 +539,7 @@ export function createEditor(config: EditorConfig = {}): EditorInstance {
539
539
  const v = view.peek()
540
540
  if (!v) return
541
541
  v.dispatch({
542
- effects: EditorView.scrollIntoView(pos, { y: "center" }),
542
+ effects: EditorView.scrollIntoView(pos, { y: 'center' }),
543
543
  })
544
544
  }
545
545
 
@@ -550,8 +550,8 @@ export function createEditor(config: EditorConfig = {}): EditorInstance {
550
550
  if (!v) return
551
551
 
552
552
  // Use string concat to prevent Vite from statically analyzing these optional imports
553
- const vimPkg = "@replit/codemirror-" + "vim"
554
- const emacsPkg = "@replit/codemirror-" + "emacs"
553
+ const vimPkg = '@replit/codemirror-' + 'vim'
554
+ const emacsPkg = '@replit/codemirror-' + 'emacs'
555
555
 
556
556
  if (enableVim) {
557
557
  try {
package/src/index.ts CHANGED
@@ -24,17 +24,17 @@
24
24
  */
25
25
 
26
26
  // Components
27
- export { CodeEditor } from "./components/code-editor"
28
- export { DiffEditor } from "./components/diff-editor"
29
- export { TabbedEditor } from "./components/tabbed-editor"
27
+ export { CodeEditor } from './components/code-editor'
28
+ export { DiffEditor } from './components/diff-editor'
29
+ export { TabbedEditor } from './components/tabbed-editor'
30
30
  // Core
31
- export { createEditor } from "./editor"
31
+ export { createEditor } from './editor'
32
32
  // Languages
33
- export { getAvailableLanguages, loadLanguage } from "./languages"
33
+ export { getAvailableLanguages, loadLanguage } from './languages'
34
34
  // Minimap
35
- export { minimapExtension } from "./minimap"
35
+ export { minimapExtension } from './minimap'
36
36
  // Themes
37
- export { darkTheme, lightTheme, resolveTheme } from "./themes"
37
+ export { darkTheme, lightTheme, resolveTheme } from './themes'
38
38
 
39
39
  // Types
40
40
  export type {
@@ -49,4 +49,4 @@ export type {
49
49
  TabbedEditorConfig,
50
50
  TabbedEditorInstance,
51
51
  TabbedEditorProps,
52
- } from "./types"
52
+ } from './types'
package/src/languages.ts CHANGED
@@ -1,32 +1,32 @@
1
- import type { Extension } from "@codemirror/state"
2
- import type { EditorLanguage } from "./types"
1
+ import type { Extension } from '@codemirror/state'
2
+ import type { EditorLanguage } from './types'
3
3
 
4
4
  /**
5
5
  * Language extension loaders — lazy-loaded on demand.
6
6
  * Only the requested language is imported, keeping the initial bundle small.
7
7
  */
8
8
  const languageLoaders: Record<EditorLanguage, () => Promise<Extension>> = {
9
- javascript: () => import("@codemirror/lang-javascript").then((m) => m.javascript()),
9
+ javascript: () => import('@codemirror/lang-javascript').then((m) => m.javascript()),
10
10
  typescript: () =>
11
- import("@codemirror/lang-javascript").then((m) => m.javascript({ typescript: true })),
12
- jsx: () => import("@codemirror/lang-javascript").then((m) => m.javascript({ jsx: true })),
11
+ import('@codemirror/lang-javascript').then((m) => m.javascript({ typescript: true })),
12
+ jsx: () => import('@codemirror/lang-javascript').then((m) => m.javascript({ jsx: true })),
13
13
  tsx: () =>
14
- import("@codemirror/lang-javascript").then((m) =>
14
+ import('@codemirror/lang-javascript').then((m) =>
15
15
  m.javascript({ typescript: true, jsx: true }),
16
16
  ),
17
- html: () => import("@codemirror/lang-html").then((m) => m.html()),
18
- css: () => import("@codemirror/lang-css").then((m) => m.css()),
19
- json: () => import("@codemirror/lang-json").then((m) => m.json()),
20
- markdown: () => import("@codemirror/lang-markdown").then((m) => m.markdown()),
21
- python: () => import("@codemirror/lang-python").then((m) => m.python()),
22
- rust: () => import("@codemirror/lang-rust").then((m) => m.rust()),
23
- sql: () => import("@codemirror/lang-sql").then((m) => m.sql()),
24
- xml: () => import("@codemirror/lang-xml").then((m) => m.xml()),
25
- yaml: () => import("@codemirror/lang-yaml").then((m) => m.yaml()),
26
- cpp: () => import("@codemirror/lang-cpp").then((m) => m.cpp()),
27
- java: () => import("@codemirror/lang-java").then((m) => m.java()),
28
- go: () => import("@codemirror/lang-go").then((m) => m.go()),
29
- php: () => import("@codemirror/lang-php").then((m) => m.php()),
17
+ html: () => import('@codemirror/lang-html').then((m) => m.html()),
18
+ css: () => import('@codemirror/lang-css').then((m) => m.css()),
19
+ json: () => import('@codemirror/lang-json').then((m) => m.json()),
20
+ markdown: () => import('@codemirror/lang-markdown').then((m) => m.markdown()),
21
+ python: () => import('@codemirror/lang-python').then((m) => m.python()),
22
+ rust: () => import('@codemirror/lang-rust').then((m) => m.rust()),
23
+ sql: () => import('@codemirror/lang-sql').then((m) => m.sql()),
24
+ xml: () => import('@codemirror/lang-xml').then((m) => m.xml()),
25
+ yaml: () => import('@codemirror/lang-yaml').then((m) => m.yaml()),
26
+ cpp: () => import('@codemirror/lang-cpp').then((m) => m.cpp()),
27
+ java: () => import('@codemirror/lang-java').then((m) => m.java()),
28
+ go: () => import('@codemirror/lang-go').then((m) => m.go()),
29
+ php: () => import('@codemirror/lang-php').then((m) => m.php()),
30
30
  ruby: () => Promise.resolve([]),
31
31
  shell: () => Promise.resolve([]),
32
32
  plain: () => Promise.resolve([]),
package/src/minimap.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { Extension } from "@codemirror/state"
2
- import { EditorView, ViewPlugin, type ViewUpdate } from "@codemirror/view"
1
+ import type { Extension } from '@codemirror/state'
2
+ import { EditorView, ViewPlugin, type ViewUpdate } from '@codemirror/view'
3
3
 
4
4
  /**
5
5
  * Canvas-based minimap extension for CodeMirror 6.
@@ -9,22 +9,22 @@ import { EditorView, ViewPlugin, type ViewUpdate } from "@codemirror/view"
9
9
  const MINIMAP_WIDTH = 80
10
10
  const CHAR_WIDTH = 1.2
11
11
  const LINE_HEIGHT = 2.5
12
- const MINIMAP_BG = "#1e1e2e"
13
- const MINIMAP_BG_LIGHT = "#f8fafc"
14
- const TEXT_COLOR = "#585b70"
15
- const TEXT_COLOR_LIGHT = "#94a3b8"
16
- const VIEWPORT_COLOR = "rgba(59, 130, 246, 0.15)"
17
- const VIEWPORT_BORDER = "rgba(59, 130, 246, 0.4)"
12
+ const MINIMAP_BG = '#1e1e2e'
13
+ const MINIMAP_BG_LIGHT = '#f8fafc'
14
+ const TEXT_COLOR = '#585b70'
15
+ const TEXT_COLOR_LIGHT = '#94a3b8'
16
+ const VIEWPORT_COLOR = 'rgba(59, 130, 246, 0.15)'
17
+ const VIEWPORT_BORDER = 'rgba(59, 130, 246, 0.4)'
18
18
 
19
19
  function createMinimapCanvas(): HTMLCanvasElement {
20
- const canvas = document.createElement("canvas")
20
+ const canvas = document.createElement('canvas')
21
21
  canvas.style.cssText = `position: absolute; right: 0; top: 0; width: ${MINIMAP_WIDTH}px; height: 100%; cursor: pointer; z-index: 5;`
22
22
  canvas.width = MINIMAP_WIDTH * 2 // retina
23
23
  return canvas
24
24
  }
25
25
 
26
26
  function renderMinimap(canvas: HTMLCanvasElement, view: EditorView): void {
27
- const ctx = canvas.getContext("2d")
27
+ const ctx = canvas.getContext('2d')
28
28
  if (!ctx) return
29
29
 
30
30
  const doc = view.state.doc
@@ -32,7 +32,7 @@ function renderMinimap(canvas: HTMLCanvasElement, view: EditorView): void {
32
32
  const height = canvas.clientHeight
33
33
  canvas.height = height * 2 // retina
34
34
 
35
- const isDark = view.dom.classList.contains("cm-dark")
35
+ const isDark = view.dom.classList.contains('cm-dark')
36
36
  const bg = isDark ? MINIMAP_BG : MINIMAP_BG_LIGHT
37
37
  const textColor = isDark ? TEXT_COLOR : TEXT_COLOR_LIGHT
38
38
 
@@ -64,7 +64,7 @@ function renderMinimap(canvas: HTMLCanvasElement, view: EditorView): void {
64
64
  const text = line.text
65
65
  let x = 4
66
66
  for (let j = 0; j < Math.min(text.length, 60); j++) {
67
- if (text[j] !== " " && text[j] !== "\t") {
67
+ if (text[j] !== ' ' && text[j] !== '\t') {
68
68
  ctx.fillRect(x, y, CHAR_WIDTH, 1.5)
69
69
  }
70
70
  x += CHAR_WIDTH
@@ -107,17 +107,17 @@ export function minimapExtension(): Extension {
107
107
  constructor(view: EditorView) {
108
108
  this.view = view
109
109
  this.canvas = createMinimapCanvas()
110
- view.dom.style.position = "relative"
110
+ view.dom.style.position = 'relative'
111
111
  view.dom.appendChild(this.canvas)
112
112
 
113
113
  // Click to scroll
114
- this.canvas.addEventListener("click", (e) => {
114
+ this.canvas.addEventListener('click', (e) => {
115
115
  const rect = this.canvas.getBoundingClientRect()
116
116
  const clickY = e.clientY - rect.top
117
117
  const fraction = clickY / rect.height
118
118
  const scrollTarget =
119
119
  fraction * (view.scrollDOM.scrollHeight - view.scrollDOM.clientHeight)
120
- view.scrollDOM.scrollTo({ top: scrollTarget, behavior: "smooth" })
120
+ view.scrollDOM.scrollTo({ top: scrollTarget, behavior: 'smooth' })
121
121
  })
122
122
 
123
123
  this.render()
@@ -142,7 +142,7 @@ export function minimapExtension(): Extension {
142
142
  ),
143
143
  // Add padding on the right for the minimap
144
144
  EditorView.theme({
145
- ".cm-scroller": {
145
+ '.cm-scroller': {
146
146
  paddingRight: `${MINIMAP_WIDTH + 8}px`,
147
147
  },
148
148
  }),
@@ -1,6 +1,6 @@
1
- import { computed, signal } from "@pyreon/reactivity"
2
- import { createEditor } from "./editor"
3
- import type { EditorLanguage, Tab, TabbedEditorConfig, TabbedEditorInstance } from "./types"
1
+ import { computed, signal } from '@pyreon/reactivity'
2
+ import { createEditor } from './editor'
3
+ import type { EditorLanguage, Tab, TabbedEditorConfig, TabbedEditorInstance } from './types'
4
4
 
5
5
  /**
6
6
  * Create a tabbed code editor — multiple files with tab management.
@@ -42,7 +42,7 @@ export function createTabbedEditor(config: TabbedEditorConfig = {}): TabbedEdito
42
42
  // ── State ──────────────────────────────────────────────────────────────
43
43
 
44
44
  const tabs = signal<Tab[]>(tabsWithIds)
45
- const activeTabId = signal(tabsWithIds[0]?.id ?? "")
45
+ const activeTabId = signal(tabsWithIds[0]?.id ?? '')
46
46
 
47
47
  // Content cache — stores each tab's current content
48
48
  const contentCache = new Map<string, string>()
@@ -59,8 +59,8 @@ export function createTabbedEditor(config: TabbedEditorConfig = {}): TabbedEdito
59
59
  Object.entries(editorConfig).filter(([_, v]) => v !== undefined),
60
60
  )
61
61
  const editor = createEditor({
62
- value: firstTab?.value ?? "",
63
- language: (firstTab?.language ?? "plain") as EditorLanguage,
62
+ value: firstTab?.value ?? '',
63
+ language: (firstTab?.language ?? 'plain') as EditorLanguage,
64
64
  ...(theme != null ? { theme } : {}),
65
65
  ...filteredConfig,
66
66
  onChange: (value) => {
@@ -106,7 +106,7 @@ export function createTabbedEditor(config: TabbedEditorConfig = {}): TabbedEdito
106
106
  // Restore target tab content
107
107
  const cached = contentCache.get(id)
108
108
  editor.value.set(cached ?? tab.value)
109
- editor.language.set((tab.language ?? "plain") as EditorLanguage)
109
+ editor.language.set((tab.language ?? 'plain') as EditorLanguage)
110
110
  }
111
111
 
112
112
  function openTab(tab: Tab): void {
@@ -145,8 +145,8 @@ export function createTabbedEditor(config: TabbedEditorConfig = {}): TabbedEdito
145
145
  const nextTab = remaining[nextIndex]
146
146
  if (nextTab) switchTab(nextTab.id ?? nextTab.name)
147
147
  } else {
148
- activeTabId.set("")
149
- editor.value.set("")
148
+ activeTabId.set('')
149
+ editor.value.set('')
150
150
  }
151
151
  }
152
152
  }
@@ -183,8 +183,8 @@ export function createTabbedEditor(config: TabbedEditorConfig = {}): TabbedEdito
183
183
  const first = remaining[0]
184
184
  if (first) switchTab(first.id ?? first.name)
185
185
  } else {
186
- activeTabId.set("")
187
- editor.value.set("")
186
+ activeTabId.set('')
187
+ editor.value.set('')
188
188
  }
189
189
  }
190
190