@almadar/shell-web 0.0.0-stage → 0.1.0
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/bundling.d.mts +18 -0
- package/bundling.mjs +28 -0
- package/dist/ArbitraryClassCompiler-Mzabq-UB.d.ts +100 -0
- package/dist/AvlGlyph-JKJOAH23.js +6 -0
- package/dist/AvlStateMachine-PI4YGREK.js +8 -0
- package/dist/AvlTransitionDetail-ZH7V24UG.js +12 -0
- package/dist/AvlTransitionExplainer-ZSRT7L6Y.js +13 -0
- package/dist/BehaviorValueFrame-6RUJXT4A.js +29 -0
- package/dist/BehaviorValueFrame-SSEMEBTG.css +1756 -0
- package/dist/BehaviorView-RFEE5J6E.js +10 -0
- package/dist/Canvas3DHost-_Y-5uLM_.d.ts +552 -0
- package/dist/EventBusProvider-CVwjkV_2.d.ts +284 -0
- package/dist/FileTree-BCFnBEuQ.d.ts +254 -0
- package/dist/FlowCanvas-3JRMNJLV.css +1756 -0
- package/dist/FlowCanvas-STDC4OWK.js +27 -0
- package/dist/GameAudioProvider-Cm9BnvmP.d.ts +93 -0
- package/dist/KaTeX_AMS-Regular-CYEKBG2K.woff +0 -0
- package/dist/KaTeX_AMS-Regular-JKX5W2C4.ttf +0 -0
- package/dist/KaTeX_AMS-Regular-U6PRYMIZ.woff2 +0 -0
- package/dist/KaTeX_Caligraphic-Bold-5QL5CMTE.woff2 +0 -0
- package/dist/KaTeX_Caligraphic-Bold-WZ3QSGD3.woff +0 -0
- package/dist/KaTeX_Caligraphic-Bold-ZTS3R3HK.ttf +0 -0
- package/dist/KaTeX_Caligraphic-Regular-3LKEU76G.woff +0 -0
- package/dist/KaTeX_Caligraphic-Regular-A7XRTZ5Q.ttf +0 -0
- package/dist/KaTeX_Caligraphic-Regular-KX5MEWCF.woff2 +0 -0
- package/dist/KaTeX_Fraktur-Bold-2QVFK6NQ.woff2 +0 -0
- package/dist/KaTeX_Fraktur-Bold-T4SWXBMT.woff +0 -0
- package/dist/KaTeX_Fraktur-Bold-WGHVTYOR.ttf +0 -0
- package/dist/KaTeX_Fraktur-Regular-2PEIFJSJ.woff2 +0 -0
- package/dist/KaTeX_Fraktur-Regular-5U4OPH2X.ttf +0 -0
- package/dist/KaTeX_Fraktur-Regular-PQMHCIK6.woff +0 -0
- package/dist/KaTeX_Main-Bold-2GA4IZIN.woff +0 -0
- package/dist/KaTeX_Main-Bold-W5FBVCZM.ttf +0 -0
- package/dist/KaTeX_Main-Bold-YP5VVQRP.woff2 +0 -0
- package/dist/KaTeX_Main-BoldItalic-4P4C7HJH.woff +0 -0
- package/dist/KaTeX_Main-BoldItalic-N4V3DX7S.woff2 +0 -0
- package/dist/KaTeX_Main-BoldItalic-ODMLBJJQ.ttf +0 -0
- package/dist/KaTeX_Main-Italic-I43T2HSR.ttf +0 -0
- package/dist/KaTeX_Main-Italic-RELBIK7M.woff2 +0 -0
- package/dist/KaTeX_Main-Italic-SASNQFN2.woff +0 -0
- package/dist/KaTeX_Main-Regular-ARRPAO67.woff2 +0 -0
- package/dist/KaTeX_Main-Regular-P5I74A2A.woff +0 -0
- package/dist/KaTeX_Main-Regular-W74P5G27.ttf +0 -0
- package/dist/KaTeX_Math-BoldItalic-6EBV3DK5.woff +0 -0
- package/dist/KaTeX_Math-BoldItalic-K4WTGH3J.woff2 +0 -0
- package/dist/KaTeX_Math-BoldItalic-VB447A4D.ttf +0 -0
- package/dist/KaTeX_Math-Italic-6KGCHLFN.woff2 +0 -0
- package/dist/KaTeX_Math-Italic-KKK3USB2.woff +0 -0
- package/dist/KaTeX_Math-Italic-SON4MRCA.ttf +0 -0
- package/dist/KaTeX_SansSerif-Bold-RRNVJFFW.woff2 +0 -0
- package/dist/KaTeX_SansSerif-Bold-STQ6RXC7.ttf +0 -0
- package/dist/KaTeX_SansSerif-Bold-X5M5EMOD.woff +0 -0
- package/dist/KaTeX_SansSerif-Italic-HMPFTM52.woff2 +0 -0
- package/dist/KaTeX_SansSerif-Italic-PSN4QKYX.woff +0 -0
- package/dist/KaTeX_SansSerif-Italic-WTBAZBGY.ttf +0 -0
- package/dist/KaTeX_SansSerif-Regular-2TL3USAE.ttf +0 -0
- package/dist/KaTeX_SansSerif-Regular-OQCII6EP.woff +0 -0
- package/dist/KaTeX_SansSerif-Regular-XIQ62X4E.woff2 +0 -0
- package/dist/KaTeX_Script-Regular-72OLXYNA.ttf +0 -0
- package/dist/KaTeX_Script-Regular-A5IFOEBS.woff +0 -0
- package/dist/KaTeX_Script-Regular-APUWIHLP.woff2 +0 -0
- package/dist/KaTeX_Size1-Regular-4HRHTS65.woff +0 -0
- package/dist/KaTeX_Size1-Regular-5LRUTBFT.woff2 +0 -0
- package/dist/KaTeX_Size1-Regular-7K6AASVL.ttf +0 -0
- package/dist/KaTeX_Size2-Regular-222HN3GT.ttf +0 -0
- package/dist/KaTeX_Size2-Regular-K5ZHAIS6.woff +0 -0
- package/dist/KaTeX_Size2-Regular-LELKET5D.woff2 +0 -0
- package/dist/KaTeX_Size3-Regular-TLFPAHDE.woff +0 -0
- package/dist/KaTeX_Size3-Regular-UFCO6WCA.ttf +0 -0
- package/dist/KaTeX_Size3-Regular-WQRQ47UD.woff2 +0 -0
- package/dist/KaTeX_Size4-Regular-7PGNVPQK.ttf +0 -0
- package/dist/KaTeX_Size4-Regular-CDMV7U5C.woff2 +0 -0
- package/dist/KaTeX_Size4-Regular-PKMWZHNC.woff +0 -0
- package/dist/KaTeX_Typewriter-Regular-3F5K6SQ6.ttf +0 -0
- package/dist/KaTeX_Typewriter-Regular-MJMFSK64.woff +0 -0
- package/dist/KaTeX_Typewriter-Regular-VBYJ4NRC.woff2 +0 -0
- package/dist/KernelEngineContext-BOCQoFwk.d.ts +43 -0
- package/dist/LayersPanel-BBQ54IVG.js +7 -0
- package/dist/ModuleCard-3TT2X7IW.js +7 -0
- package/dist/OrbInspector-K6T6O7GI.js +27 -0
- package/dist/OrbInspector-MHLJ6OEE.css +1756 -0
- package/dist/Select-mDZIwNqN.d.ts +199 -0
- package/dist/ServerBridge-Cm1On51b.d.ts +233 -0
- package/dist/ThemeContext-DJmO59xd.d.ts +147 -0
- package/dist/TraitValueFrame-2PJGLLVI.js +28 -0
- package/dist/TraitValueFrame-4G3KOUBR.css +1756 -0
- package/dist/UISlotContext-Dl_ewwCI.d.ts +79 -0
- package/dist/UISlotRenderer-JKFSX24W.js +27 -0
- package/dist/UISlotRenderer-KVFO6J7R.css +1756 -0
- package/dist/UserContext-DqWeZkUZ.d.ts +100 -0
- package/dist/auth/browser/index.d.ts +2 -0
- package/dist/auth/browser/index.js +1 -0
- package/dist/auth/react/index.d.ts +49 -0
- package/dist/auth/react/index.js +119 -0
- package/dist/avl/index.css +1756 -0
- package/dist/avl/index.d.ts +2238 -0
- package/dist/avl/index.js +2693 -0
- package/dist/avl-3d-context-BIRKWpaL.d.ts +204 -0
- package/dist/avl-schema-parser-CtJxJ9KU.d.ts +132 -0
- package/dist/avl-zoom-state-CKMVuBFg.d.ts +17 -0
- package/dist/chunk-2PY54Z44.js +227 -0
- package/dist/chunk-2QOH2HWM.js +95 -0
- package/dist/chunk-3BBUBJFF.js +339 -0
- package/dist/chunk-42FY4RYA.js +191 -0
- package/dist/chunk-5QTYQTPS.js +15 -0
- package/dist/chunk-6P3MWXYE.js +440 -0
- package/dist/chunk-73SRAB4P.js +1053 -0
- package/dist/chunk-A2LR6VQQ.js +349 -0
- package/dist/chunk-AILY3XPS.js +562 -0
- package/dist/chunk-B4BU77LT.js +432 -0
- package/dist/chunk-DFNZUYX4.js +378 -0
- package/dist/chunk-DJ433ET5.js +1327 -0
- package/dist/chunk-DLZF4PVE.js +24 -0
- package/dist/chunk-DYEKAA4L.js +787 -0
- package/dist/chunk-DZ42OJQC.js +176 -0
- package/dist/chunk-EOWMARUB.js +16 -0
- package/dist/chunk-EQAMU2ZC.js +14 -0
- package/dist/chunk-FAJDTHWC.js +98 -0
- package/dist/chunk-FIW6WN23.js +508 -0
- package/dist/chunk-FP3WIKTC.js +303 -0
- package/dist/chunk-G7DCAZ22.js +19 -0
- package/dist/chunk-GAR5TQ5B.js +199 -0
- package/dist/chunk-GKIFONTE.js +131 -0
- package/dist/chunk-GYTPOFVC.js +47155 -0
- package/dist/chunk-KVQS4GXU.js +328 -0
- package/dist/chunk-L2DEKY4J.js +97 -0
- package/dist/chunk-L677XGY3.js +701 -0
- package/dist/chunk-MBQAMMSE.js +11877 -0
- package/dist/chunk-P4LNHAFI.js +1051 -0
- package/dist/chunk-P4ZFUQFF.js +93 -0
- package/dist/chunk-PC7K4SK7.js +1384 -0
- package/dist/chunk-R5O5AUPI.js +573 -0
- package/dist/chunk-SGM3FASH.js +672 -0
- package/dist/chunk-SJGJJKBY.js +502 -0
- package/dist/chunk-TESBIVUA.js +11 -0
- package/dist/chunk-TZZBINQY.js +82 -0
- package/dist/chunk-U6QRZASX.js +280 -0
- package/dist/chunk-VFF5OO47.js +319 -0
- package/dist/chunk-YDNJLLG6.js +516 -0
- package/dist/chunk-YHMRX6YA.js +455 -0
- package/dist/chunk-ZO6MXAS3.js +69 -0
- package/dist/components/index.css +1756 -0
- package/dist/components/index.d.ts +11093 -0
- package/dist/components/index.js +1110 -0
- package/dist/context/index.d.ts +9 -0
- package/dist/context/index.js +7 -0
- package/dist/core.d.ts +2523 -0
- package/dist/core.js +2 -0
- package/dist/design-classes/index.cjs +429 -0
- package/dist/design-classes/index.d.cts +165 -0
- package/dist/design-classes/index.d.ts +165 -0
- package/dist/design-classes/index.js +397 -0
- package/dist/emojiItems-QGSNAABW.js +20 -0
- package/dist/fx-CmQjnHmT.d.ts +371 -0
- package/dist/hooks/index.d.ts +936 -0
- package/dist/hooks/index.js +7 -0
- package/dist/index.d.ts +486 -0
- package/dist/index.js +38 -0
- package/dist/katexPlugin-FA7NX4PE.css +1161 -0
- package/dist/katexPlugin-NCDKOOQY.js +2 -0
- package/dist/kernel-client-ZH4PSMCN.js +367 -0
- package/dist/kernel-wire-B4S8pnP3.d.ts +65 -0
- package/dist/lib/index.d.ts +602 -0
- package/dist/lib/index.js +1288 -0
- package/dist/paintDispatch-ChW5mVuK.d.ts +698 -0
- package/dist/parseLessonSegments-GpCeMrb2.d.ts +334 -0
- package/dist/perf-CKiBKbkw.d.ts +22 -0
- package/dist/perf-Dr28-AgT.d.ts +57 -0
- package/dist/prism-AIWGN2X5.js +134 -0
- package/dist/providers/index.css +1756 -0
- package/dist/providers/index.d.ts +340 -0
- package/dist/providers/index.js +30 -0
- package/dist/renderer/index.d.ts +467 -0
- package/dist/renderer/index.js +3 -0
- package/dist/runtime/index.css +1756 -0
- package/dist/runtime/index.d.ts +440 -0
- package/dist/runtime/index.js +31 -0
- package/dist/slot-host-CPzrxLo9.d.ts +48 -0
- package/dist/ssr/index.cjs +7631 -0
- package/dist/ssr/index.d.cts +487 -0
- package/dist/ssr/index.d.ts +487 -0
- package/dist/ssr/index.js +7599 -0
- package/dist/storage/browser/index.d.ts +1 -0
- package/dist/storage/browser/index.js +1 -0
- package/dist/test-support.d.ts +35 -0
- package/dist/test-support.js +114 -0
- package/dist/themeTokens-CRd8AEDF.d.ts +125 -0
- package/dist/three/index.css +503 -0
- package/dist/three/index.d.ts +1185 -0
- package/dist/three/index.js +3896 -0
- package/dist/useKeyboardRouter-Dsq553Ur.d.ts +42 -0
- package/dist/useUISlots-CiobNFGb.d.ts +211 -0
- package/dist/verification-C5pTeMJv.d.ts +66 -0
- package/dist/verificationRegistry-CabxhfTv.d.ts +122 -0
- package/dist/wrapCallbackForEvent-B9QLbhxX.d.ts +19 -0
- package/index.css +199 -0
- package/package.json +269 -3
- package/src/core/locales/ar.json +1263 -0
- package/src/core/locales/en.json +1263 -0
- package/src/core/locales/index.ts +54 -0
- package/src/core/locales/sl.json +1263 -0
- package/src/core/tokens/native-tokens.json +369 -0
- package/tailwind-compile.cjs +29 -0
- package/tailwind-preset.cjs +991 -0
- package/themes/_base.css +451 -0
- package/themes/_contract.md +307 -0
- package/themes/_fonts-kenney.css +11 -0
- package/themes/_fonts.css +12 -0
- package/themes/_foundation.css +105 -0
- package/themes/_head.css +22 -0
- package/themes/_presets.css +67 -0
- package/themes/almadar-heritage.css +455 -0
- package/themes/almadar-website.css +269 -0
- package/themes/almadar.css +269 -0
- package/themes/aqua.css +455 -0
- package/themes/arabesque.css +459 -0
- package/themes/art-deco.css +457 -0
- package/themes/art-nouveau.css +459 -0
- package/themes/atelier.css +463 -0
- package/themes/bauhaus.css +461 -0
- package/themes/bloomberg-dense.css +463 -0
- package/themes/blueprint.css +457 -0
- package/themes/clay.css +449 -0
- package/themes/comic.css +453 -0
- package/themes/constructivist.css +457 -0
- package/themes/corporate.css +449 -0
- package/themes/cyberpunk.css +453 -0
- package/themes/frutiger-aero.css +458 -0
- package/themes/game-adventure.css +201 -0
- package/themes/game-rpg.css +203 -0
- package/themes/game-sci-fi.css +201 -0
- package/themes/game-ui-pack.css +200 -0
- package/themes/gazette.css +449 -0
- package/themes/glass.css +457 -0
- package/themes/gothic.css +453 -0
- package/themes/index.css +21 -0
- package/themes/ink-wash.css +459 -0
- package/themes/kawaii.css +459 -0
- package/themes/kflow.css +310 -0
- package/themes/kiosk.css +449 -0
- package/themes/linear-clean.css +463 -0
- package/themes/luxury.css +451 -0
- package/themes/mac-classic.css +455 -0
- package/themes/material.css +463 -0
- package/themes/memphis.css +453 -0
- package/themes/mid-century.css +455 -0
- package/themes/minimalist.css +449 -0
- package/themes/mudcloth.css +459 -0
- package/themes/nata.css +310 -0
- package/themes/neon.css +453 -0
- package/themes/neumorphic.css +451 -0
- package/themes/newsprint.css +455 -0
- package/themes/notion-editorial.css +463 -0
- package/themes/orb.css +465 -0
- package/themes/pixel.css +449 -0
- package/themes/prism.css +309 -0
- package/themes/rawi.css +310 -0
- package/themes/retro.css +452 -0
- package/themes/risograph.css +463 -0
- package/themes/scandi.css +469 -0
- package/themes/sketch.css +455 -0
- package/themes/solarpunk.css +469 -0
- package/themes/steampunk.css +451 -0
- package/themes/swiss.css +455 -0
- package/themes/terminal.css +466 -0
- package/themes/trait-wars.css +487 -0
- package/themes/ukiyo-e.css +459 -0
- package/themes/vaporwave.css +455 -0
- package/themes/victorian.css +453 -0
- package/themes/wabi-sabi.css +459 -0
- package/themes/win95.css +455 -0
- package/themes/wireframe.css +439 -0
- package/themes/zine.css +455 -0
- package/README.md +0 -3
|
@@ -0,0 +1,1051 @@
|
|
|
1
|
+
import { perfStore, pushPerfEntry } from './chunk-DYEKAA4L.js';
|
|
2
|
+
import { isMotionEnabled } from './chunk-MBQAMMSE.js';
|
|
3
|
+
import { useRef, useLayoutEffect, useSyncExternalStore } from 'react';
|
|
4
|
+
import { ENTER_DELAY_STEPS, ENTER_ANIMATIONS, isFileValue } from '@almadar/core';
|
|
5
|
+
export { getNestedValue } from '@almadar/core';
|
|
6
|
+
import { createLogger, isLogLevelEnabled } from '@almadar/logger';
|
|
7
|
+
|
|
8
|
+
var ENTER_SLOT_CLASS = "almadar-enter-slot";
|
|
9
|
+
function asEnterAnimation(value) {
|
|
10
|
+
return ENTER_ANIMATIONS.find((e) => e === value);
|
|
11
|
+
}
|
|
12
|
+
var MAX_ENTER_DELAY = ENTER_DELAY_STEPS.length;
|
|
13
|
+
function enterClassName(enter, enterDelay) {
|
|
14
|
+
if (enter === void 0 || enter === "none" || !isMotionEnabled()) return void 0;
|
|
15
|
+
const base = `almadar-enter-${enter}`;
|
|
16
|
+
if (enterDelay === void 0 || !Number.isInteger(enterDelay) || enterDelay < 1 || enterDelay > MAX_ENTER_DELAY) return base;
|
|
17
|
+
return `${base} almadar-enter-delay-${enterDelay}`;
|
|
18
|
+
}
|
|
19
|
+
function slotPlaysDefaultEnter(rootEnter) {
|
|
20
|
+
return rootEnter === void 0 && isMotionEnabled();
|
|
21
|
+
}
|
|
22
|
+
function useSlotEnterRestart(ref, contentKey, active) {
|
|
23
|
+
const lastKey = useRef(contentKey);
|
|
24
|
+
useLayoutEffect(() => {
|
|
25
|
+
if (lastKey.current === contentKey) return;
|
|
26
|
+
lastKey.current = contentKey;
|
|
27
|
+
const el = ref.current;
|
|
28
|
+
if (!el || !active) return;
|
|
29
|
+
el.classList.remove(ENTER_SLOT_CLASS);
|
|
30
|
+
void el.offsetWidth;
|
|
31
|
+
el.classList.add(ENTER_SLOT_CLASS);
|
|
32
|
+
}, [contentKey, active, ref]);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// src/lib/editorMotions.ts
|
|
36
|
+
var EDITOR_MOTIONS = [
|
|
37
|
+
"left",
|
|
38
|
+
"right",
|
|
39
|
+
"up",
|
|
40
|
+
"down",
|
|
41
|
+
"word-forward",
|
|
42
|
+
"word-back",
|
|
43
|
+
"word-end",
|
|
44
|
+
"line-start",
|
|
45
|
+
"line-end",
|
|
46
|
+
"first-nonblank",
|
|
47
|
+
"doc-start",
|
|
48
|
+
"doc-end",
|
|
49
|
+
"paragraph-forward",
|
|
50
|
+
"paragraph-back",
|
|
51
|
+
"line",
|
|
52
|
+
"selection",
|
|
53
|
+
"match-bracket"
|
|
54
|
+
];
|
|
55
|
+
var EDITOR_OPERATORS = [
|
|
56
|
+
"delete",
|
|
57
|
+
"yank",
|
|
58
|
+
"change",
|
|
59
|
+
"put",
|
|
60
|
+
"put-before",
|
|
61
|
+
"undo",
|
|
62
|
+
"redo",
|
|
63
|
+
"join",
|
|
64
|
+
"toggle-case",
|
|
65
|
+
"indent",
|
|
66
|
+
"dedent",
|
|
67
|
+
"replace"
|
|
68
|
+
];
|
|
69
|
+
var EDITOR_MOTION_SET = new Set(EDITOR_MOTIONS);
|
|
70
|
+
var EDITOR_OPERATOR_SET = new Set(EDITOR_OPERATORS);
|
|
71
|
+
function isEditorMotion(value) {
|
|
72
|
+
return EDITOR_MOTION_SET.has(value);
|
|
73
|
+
}
|
|
74
|
+
function isEditorOperator(value) {
|
|
75
|
+
return EDITOR_OPERATOR_SET.has(value);
|
|
76
|
+
}
|
|
77
|
+
var INDENT_UNIT = " ";
|
|
78
|
+
function clamp(value, min, max) {
|
|
79
|
+
return Math.max(min, Math.min(max, value));
|
|
80
|
+
}
|
|
81
|
+
function computeLines(text) {
|
|
82
|
+
const lines = [];
|
|
83
|
+
let start = 0;
|
|
84
|
+
for (let i = 0; i <= text.length; i++) {
|
|
85
|
+
if (i === text.length || text[i] === "\n") {
|
|
86
|
+
lines.push({ start, end: i });
|
|
87
|
+
start = i + 1;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return lines;
|
|
91
|
+
}
|
|
92
|
+
function lineIndexAt(lines, pos) {
|
|
93
|
+
for (let i = 0; i < lines.length; i++) {
|
|
94
|
+
if (pos <= lines[i].end) return i;
|
|
95
|
+
}
|
|
96
|
+
return lines.length - 1;
|
|
97
|
+
}
|
|
98
|
+
function findWords(text) {
|
|
99
|
+
const words = [];
|
|
100
|
+
const re = /\w+|\S+/g;
|
|
101
|
+
let m;
|
|
102
|
+
while ((m = re.exec(text)) !== null) {
|
|
103
|
+
words.push({ start: m.index, end: m.index + m[0].length });
|
|
104
|
+
}
|
|
105
|
+
return words;
|
|
106
|
+
}
|
|
107
|
+
function nextWordStart(text, pos) {
|
|
108
|
+
for (const w of findWords(text)) {
|
|
109
|
+
if (w.start > pos) return w.start;
|
|
110
|
+
}
|
|
111
|
+
return text.length;
|
|
112
|
+
}
|
|
113
|
+
function prevWordStart(text, pos) {
|
|
114
|
+
let result = 0;
|
|
115
|
+
for (const w of findWords(text)) {
|
|
116
|
+
if (w.start < pos) result = w.start;
|
|
117
|
+
else break;
|
|
118
|
+
}
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
function nextWordEnd(text, pos) {
|
|
122
|
+
for (const w of findWords(text)) {
|
|
123
|
+
const lastChar = w.end - 1;
|
|
124
|
+
if (lastChar > pos) return lastChar;
|
|
125
|
+
}
|
|
126
|
+
return text.length > 0 ? text.length - 1 : 0;
|
|
127
|
+
}
|
|
128
|
+
function firstNonBlank(text, line) {
|
|
129
|
+
let i = line.start;
|
|
130
|
+
while (i < line.end && (text[i] === " " || text[i] === " ")) i++;
|
|
131
|
+
return i;
|
|
132
|
+
}
|
|
133
|
+
function nextParagraphBoundary(lines, fromLineIdx, textLength) {
|
|
134
|
+
for (let i = fromLineIdx + 1; i < lines.length; i++) {
|
|
135
|
+
if (lines[i].start === lines[i].end) return lines[i].start;
|
|
136
|
+
}
|
|
137
|
+
return textLength;
|
|
138
|
+
}
|
|
139
|
+
function prevParagraphBoundary(lines, fromLineIdx) {
|
|
140
|
+
for (let i = fromLineIdx - 1; i >= 0; i--) {
|
|
141
|
+
if (lines[i].start === lines[i].end) return lines[i].start;
|
|
142
|
+
}
|
|
143
|
+
return 0;
|
|
144
|
+
}
|
|
145
|
+
var BRACKET_PARTNER = {
|
|
146
|
+
"(": ")",
|
|
147
|
+
")": "(",
|
|
148
|
+
"[": "]",
|
|
149
|
+
"]": "[",
|
|
150
|
+
"{": "}",
|
|
151
|
+
"}": "{"
|
|
152
|
+
};
|
|
153
|
+
var OPEN_BRACKETS = /* @__PURE__ */ new Set(["(", "[", "{"]);
|
|
154
|
+
function matchBracket(text, pos) {
|
|
155
|
+
const ch = text[pos];
|
|
156
|
+
const partner = ch !== void 0 ? BRACKET_PARTNER[ch] : void 0;
|
|
157
|
+
if (partner === void 0) return null;
|
|
158
|
+
let depth = 1;
|
|
159
|
+
if (OPEN_BRACKETS.has(ch)) {
|
|
160
|
+
for (let i = pos + 1; i < text.length; i++) {
|
|
161
|
+
if (text[i] === ch) depth++;
|
|
162
|
+
else if (text[i] === partner) {
|
|
163
|
+
depth--;
|
|
164
|
+
if (depth === 0) return i;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
} else {
|
|
168
|
+
for (let i = pos - 1; i >= 0; i--) {
|
|
169
|
+
if (text[i] === ch) depth++;
|
|
170
|
+
else if (text[i] === partner) {
|
|
171
|
+
depth--;
|
|
172
|
+
if (depth === 0) return i;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
function applyMotion(text, caret, motion, count) {
|
|
179
|
+
const n = Math.max(1, count);
|
|
180
|
+
const lines = computeLines(text);
|
|
181
|
+
const lineIdx = lineIndexAt(lines, caret);
|
|
182
|
+
const line = lines[lineIdx];
|
|
183
|
+
switch (motion) {
|
|
184
|
+
case "left":
|
|
185
|
+
return clamp(caret - n, line.start, line.end);
|
|
186
|
+
case "right":
|
|
187
|
+
return clamp(caret + n, line.start, line.end);
|
|
188
|
+
case "up": {
|
|
189
|
+
const col = caret - line.start;
|
|
190
|
+
const targetIdx = clamp(lineIdx - n, 0, lines.length - 1);
|
|
191
|
+
const target = lines[targetIdx];
|
|
192
|
+
return clamp(target.start + col, target.start, target.end);
|
|
193
|
+
}
|
|
194
|
+
case "down": {
|
|
195
|
+
const col = caret - line.start;
|
|
196
|
+
const targetIdx = clamp(lineIdx + n, 0, lines.length - 1);
|
|
197
|
+
const target = lines[targetIdx];
|
|
198
|
+
return clamp(target.start + col, target.start, target.end);
|
|
199
|
+
}
|
|
200
|
+
case "word-forward": {
|
|
201
|
+
let pos = caret;
|
|
202
|
+
for (let i = 0; i < n; i++) pos = nextWordStart(text, pos);
|
|
203
|
+
return pos;
|
|
204
|
+
}
|
|
205
|
+
case "word-back": {
|
|
206
|
+
let pos = caret;
|
|
207
|
+
for (let i = 0; i < n; i++) pos = prevWordStart(text, pos);
|
|
208
|
+
return pos;
|
|
209
|
+
}
|
|
210
|
+
case "word-end": {
|
|
211
|
+
let pos = caret;
|
|
212
|
+
for (let i = 0; i < n; i++) pos = nextWordEnd(text, pos);
|
|
213
|
+
return pos;
|
|
214
|
+
}
|
|
215
|
+
case "line-start":
|
|
216
|
+
return line.start;
|
|
217
|
+
case "line-end":
|
|
218
|
+
return line.end > line.start ? line.end - 1 : line.start;
|
|
219
|
+
case "first-nonblank":
|
|
220
|
+
return firstNonBlank(text, line);
|
|
221
|
+
case "doc-start":
|
|
222
|
+
return 0;
|
|
223
|
+
case "doc-end":
|
|
224
|
+
return text.length;
|
|
225
|
+
case "paragraph-forward": {
|
|
226
|
+
let pos = caret;
|
|
227
|
+
for (let i = 0; i < n; i++) {
|
|
228
|
+
pos = nextParagraphBoundary(lines, lineIndexAt(lines, pos), text.length);
|
|
229
|
+
}
|
|
230
|
+
return pos;
|
|
231
|
+
}
|
|
232
|
+
case "paragraph-back": {
|
|
233
|
+
let pos = caret;
|
|
234
|
+
for (let i = 0; i < n; i++) {
|
|
235
|
+
pos = prevParagraphBoundary(lines, lineIndexAt(lines, pos));
|
|
236
|
+
}
|
|
237
|
+
return pos;
|
|
238
|
+
}
|
|
239
|
+
case "match-bracket": {
|
|
240
|
+
const chAtCaret = text[caret];
|
|
241
|
+
if (chAtCaret !== void 0 && BRACKET_PARTNER[chAtCaret] !== void 0) {
|
|
242
|
+
const target = matchBracket(text, caret);
|
|
243
|
+
return target === null ? caret : target;
|
|
244
|
+
}
|
|
245
|
+
for (let i = caret; i < line.end; i++) {
|
|
246
|
+
if (BRACKET_PARTNER[text[i]] !== void 0) {
|
|
247
|
+
const target = matchBracket(text, i);
|
|
248
|
+
return target === null ? caret : target;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return caret;
|
|
252
|
+
}
|
|
253
|
+
case "line":
|
|
254
|
+
case "selection":
|
|
255
|
+
return caret;
|
|
256
|
+
default: {
|
|
257
|
+
const _exhaustive = motion;
|
|
258
|
+
return _exhaustive;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
function motionRange(text, caret, motion, count, selection) {
|
|
263
|
+
if (motion === "selection") {
|
|
264
|
+
if (!selection) return [caret, caret];
|
|
265
|
+
return [Math.min(selection[0], selection[1]), Math.max(selection[0], selection[1])];
|
|
266
|
+
}
|
|
267
|
+
const lines = computeLines(text);
|
|
268
|
+
if (motion === "line") {
|
|
269
|
+
const n = Math.max(1, count);
|
|
270
|
+
const startIdx = lineIndexAt(lines, caret);
|
|
271
|
+
const endIdx = clamp(startIdx + n - 1, 0, lines.length - 1);
|
|
272
|
+
const start2 = lines[startIdx].start;
|
|
273
|
+
const rawEnd = lines[endIdx].end;
|
|
274
|
+
const end2 = rawEnd < text.length ? rawEnd + 1 : rawEnd;
|
|
275
|
+
return [start2, end2];
|
|
276
|
+
}
|
|
277
|
+
const newCaret = applyMotion(text, caret, motion, count);
|
|
278
|
+
let start = Math.min(caret, newCaret);
|
|
279
|
+
let end = Math.max(caret, newCaret);
|
|
280
|
+
if ((motion === "word-end" || motion === "line-end" || motion === "match-bracket") && newCaret !== caret) {
|
|
281
|
+
end = Math.min(Math.max(caret, newCaret) + 1, text.length);
|
|
282
|
+
} else if (motion === "word-forward" && newCaret > caret) {
|
|
283
|
+
const startLine = lineIndexAt(lines, caret);
|
|
284
|
+
const endLine = lineIndexAt(lines, newCaret);
|
|
285
|
+
if (endLine !== startLine) {
|
|
286
|
+
end = lines[startLine].end;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return [start, end];
|
|
290
|
+
}
|
|
291
|
+
function toggleCase(s) {
|
|
292
|
+
return s.replace(/[a-zA-Z]/g, (c) => c === c.toUpperCase() ? c.toLowerCase() : c.toUpperCase());
|
|
293
|
+
}
|
|
294
|
+
function applyJoin(text, caret, count, register, registerLinewise) {
|
|
295
|
+
const lines = computeLines(text);
|
|
296
|
+
const startIdx = lineIndexAt(lines, caret);
|
|
297
|
+
const n = Math.max(2, count);
|
|
298
|
+
const endIdx = clamp(startIdx + n - 1, 0, lines.length - 1);
|
|
299
|
+
if (endIdx <= startIdx) {
|
|
300
|
+
return { text, caret, register, registerLinewise };
|
|
301
|
+
}
|
|
302
|
+
const joinCaret = lines[startIdx].end;
|
|
303
|
+
let joined = text.slice(lines[startIdx].start, lines[startIdx].end);
|
|
304
|
+
for (let i = startIdx + 1; i <= endIdx; i++) {
|
|
305
|
+
const raw = text.slice(lines[i].start, lines[i].end);
|
|
306
|
+
joined += " " + raw.replace(/^[ \t]+/, "");
|
|
307
|
+
}
|
|
308
|
+
const newText = text.slice(0, lines[startIdx].start) + joined + text.slice(lines[endIdx].end);
|
|
309
|
+
return { text: newText, caret: joinCaret, register, registerLinewise };
|
|
310
|
+
}
|
|
311
|
+
function applyIndent(text, start, end, operator, register, registerLinewise) {
|
|
312
|
+
const lines = computeLines(text);
|
|
313
|
+
const startLineIdx = lineIndexAt(lines, start);
|
|
314
|
+
const lastTouchedPos = end > start ? end - 1 : start;
|
|
315
|
+
const endLineIdx = lineIndexAt(lines, lastTouchedPos);
|
|
316
|
+
let result = text;
|
|
317
|
+
for (let i = endLineIdx; i >= startLineIdx; i--) {
|
|
318
|
+
const lineStart = lines[i].start;
|
|
319
|
+
if (operator === "indent") {
|
|
320
|
+
result = result.slice(0, lineStart) + INDENT_UNIT + result.slice(lineStart);
|
|
321
|
+
} else if (result[lineStart] === " ") {
|
|
322
|
+
result = result.slice(0, lineStart) + result.slice(lineStart + 1);
|
|
323
|
+
} else {
|
|
324
|
+
let removeCount = 0;
|
|
325
|
+
while (removeCount < INDENT_UNIT.length && result[lineStart + removeCount] === " ") removeCount++;
|
|
326
|
+
result = result.slice(0, lineStart) + result.slice(lineStart + removeCount);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
const newLines = computeLines(result);
|
|
330
|
+
const caret = firstNonBlank(result, newLines[startLineIdx]);
|
|
331
|
+
return { text: result, caret, register, registerLinewise };
|
|
332
|
+
}
|
|
333
|
+
function applyPut(text, caret, operator, register, registerLinewise, count) {
|
|
334
|
+
if (register.length === 0) {
|
|
335
|
+
return { text, caret, register, registerLinewise };
|
|
336
|
+
}
|
|
337
|
+
const content = register.repeat(count);
|
|
338
|
+
const lines = computeLines(text);
|
|
339
|
+
const line = lines[lineIndexAt(lines, caret)];
|
|
340
|
+
if (registerLinewise) {
|
|
341
|
+
if (operator === "put-before") {
|
|
342
|
+
const insertPos3 = line.start;
|
|
343
|
+
return {
|
|
344
|
+
text: text.slice(0, insertPos3) + content + text.slice(insertPos3),
|
|
345
|
+
caret: insertPos3,
|
|
346
|
+
register,
|
|
347
|
+
registerLinewise
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
const nextLineIdx = lineIndexAt(lines, caret) + 1;
|
|
351
|
+
if (nextLineIdx < lines.length) {
|
|
352
|
+
const insertPos3 = lines[nextLineIdx].start;
|
|
353
|
+
return {
|
|
354
|
+
text: text.slice(0, insertPos3) + content + text.slice(insertPos3),
|
|
355
|
+
caret: insertPos3,
|
|
356
|
+
register,
|
|
357
|
+
registerLinewise
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
const insertPos2 = text.length;
|
|
361
|
+
return {
|
|
362
|
+
text: text.slice(0, insertPos2) + "\n" + content,
|
|
363
|
+
caret: insertPos2 + 1,
|
|
364
|
+
register,
|
|
365
|
+
registerLinewise
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
const insertPos = operator === "put-before" ? clamp(caret, 0, text.length) : clamp(caret + 1, line.start, line.end);
|
|
369
|
+
return {
|
|
370
|
+
text: text.slice(0, insertPos) + content + text.slice(insertPos),
|
|
371
|
+
caret: insertPos + content.length - 1,
|
|
372
|
+
register,
|
|
373
|
+
registerLinewise
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
function applyOperator(input) {
|
|
377
|
+
const { text, caret, operator, motion, register, registerLinewise } = input;
|
|
378
|
+
const count = Math.max(1, input.count);
|
|
379
|
+
const start = clamp(input.range[0], 0, text.length);
|
|
380
|
+
const end = clamp(input.range[1], start, text.length);
|
|
381
|
+
switch (operator) {
|
|
382
|
+
case "yank":
|
|
383
|
+
return { text, caret: start, register: text.slice(start, end), registerLinewise: motion === "line" };
|
|
384
|
+
case "delete":
|
|
385
|
+
case "replace": {
|
|
386
|
+
const removed = text.slice(start, end);
|
|
387
|
+
return {
|
|
388
|
+
text: text.slice(0, start) + text.slice(end),
|
|
389
|
+
caret: start,
|
|
390
|
+
register: removed,
|
|
391
|
+
registerLinewise: motion === "line"
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
case "change": {
|
|
395
|
+
if (motion === "line") {
|
|
396
|
+
const hasTrailingNewline = end > start && text[end - 1] === "\n";
|
|
397
|
+
const removeEnd = hasTrailingNewline ? end - 1 : end;
|
|
398
|
+
const removed2 = text.slice(start, removeEnd);
|
|
399
|
+
return {
|
|
400
|
+
text: text.slice(0, start) + text.slice(removeEnd),
|
|
401
|
+
caret: start,
|
|
402
|
+
register: removed2,
|
|
403
|
+
registerLinewise: true
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
const removed = text.slice(start, end);
|
|
407
|
+
return {
|
|
408
|
+
text: text.slice(0, start) + text.slice(end),
|
|
409
|
+
caret: start,
|
|
410
|
+
register: removed,
|
|
411
|
+
registerLinewise: false
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
case "put":
|
|
415
|
+
case "put-before":
|
|
416
|
+
return applyPut(text, caret, operator, register, registerLinewise, count);
|
|
417
|
+
case "join":
|
|
418
|
+
return applyJoin(text, caret, count, register, registerLinewise);
|
|
419
|
+
case "toggle-case": {
|
|
420
|
+
const toggled = toggleCase(text.slice(start, end));
|
|
421
|
+
return { text: text.slice(0, start) + toggled + text.slice(end), caret: end, register, registerLinewise };
|
|
422
|
+
}
|
|
423
|
+
case "indent":
|
|
424
|
+
case "dedent":
|
|
425
|
+
return applyIndent(text, start, end, operator, register, registerLinewise);
|
|
426
|
+
case "undo":
|
|
427
|
+
case "redo":
|
|
428
|
+
return { text, caret, register, registerLinewise };
|
|
429
|
+
default: {
|
|
430
|
+
const _exhaustive = operator;
|
|
431
|
+
return _exhaustive;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// src/lib/lineDiff.ts
|
|
437
|
+
var linesOf = (text) => text === "" ? [] : text.split("\n");
|
|
438
|
+
function computeLineDiff(before, after) {
|
|
439
|
+
const a = linesOf(before);
|
|
440
|
+
const b = linesOf(after);
|
|
441
|
+
const ops = [];
|
|
442
|
+
diffRange(a, 0, a.length, b, 0, b.length, ops);
|
|
443
|
+
const out = [];
|
|
444
|
+
let bn = 1;
|
|
445
|
+
let an = 1;
|
|
446
|
+
for (const op of ops) {
|
|
447
|
+
if (op.type === "unchanged") out.push({ type: "unchanged", beforeLineNumber: bn++, afterLineNumber: an++, content: a[op.index] });
|
|
448
|
+
else if (op.type === "removed") out.push({ type: "removed", beforeLineNumber: bn++, content: a[op.index] });
|
|
449
|
+
else out.push({ type: "added", afterLineNumber: an++, content: b[op.index] });
|
|
450
|
+
}
|
|
451
|
+
return out;
|
|
452
|
+
}
|
|
453
|
+
function diffRange(a, aLo, aHi, b, bLo, bHi, ops) {
|
|
454
|
+
let prefix = 0;
|
|
455
|
+
while (aLo + prefix < aHi && bLo + prefix < bHi && a[aLo + prefix] === b[bLo + prefix]) prefix++;
|
|
456
|
+
for (let i = 0; i < prefix; i++) ops.push({ type: "unchanged", index: aLo + i });
|
|
457
|
+
aLo += prefix;
|
|
458
|
+
bLo += prefix;
|
|
459
|
+
let suffix = 0;
|
|
460
|
+
while (aHi - suffix > aLo && bHi - suffix > bLo && a[aHi - suffix - 1] === b[bHi - suffix - 1]) suffix++;
|
|
461
|
+
const tail = aHi - suffix;
|
|
462
|
+
aHi -= suffix;
|
|
463
|
+
bHi -= suffix;
|
|
464
|
+
if (aLo === aHi) for (let j = bLo; j < bHi; j++) ops.push({ type: "added", index: j });
|
|
465
|
+
else if (bLo === bHi) for (let i = aLo; i < aHi; i++) ops.push({ type: "removed", index: i });
|
|
466
|
+
else {
|
|
467
|
+
const [x, y, u, v] = middleSnake(a, aLo, aHi, b, bLo, bHi);
|
|
468
|
+
diffRange(a, aLo, x, b, bLo, y, ops);
|
|
469
|
+
for (let i = x; i < u; i++) ops.push({ type: "unchanged", index: i });
|
|
470
|
+
diffRange(a, u, aHi, b, v, bHi, ops);
|
|
471
|
+
}
|
|
472
|
+
for (let i = 0; i < suffix; i++) ops.push({ type: "unchanged", index: tail + i });
|
|
473
|
+
}
|
|
474
|
+
function middleSnake(a, aLo, aHi, b, bLo, bHi) {
|
|
475
|
+
const n = aHi - aLo;
|
|
476
|
+
const m = bHi - bLo;
|
|
477
|
+
const delta = n - m;
|
|
478
|
+
const odd = (delta & 1) !== 0;
|
|
479
|
+
const max = Math.ceil((n + m) / 2);
|
|
480
|
+
const offset = max + 1;
|
|
481
|
+
const forward = new Int32Array(2 * max + 3);
|
|
482
|
+
const backward = new Int32Array(2 * max + 3);
|
|
483
|
+
for (let d = 0; d <= max; d++) {
|
|
484
|
+
for (let k = -d; k <= d; k += 2) {
|
|
485
|
+
let x = k === -d || k !== d && forward[offset + k - 1] < forward[offset + k + 1] ? forward[offset + k + 1] : forward[offset + k - 1] + 1;
|
|
486
|
+
let y = x - k;
|
|
487
|
+
const x0 = x;
|
|
488
|
+
const y0 = y;
|
|
489
|
+
while (x < n && y < m && a[aLo + x] === b[bLo + y]) {
|
|
490
|
+
x++;
|
|
491
|
+
y++;
|
|
492
|
+
}
|
|
493
|
+
forward[offset + k] = x;
|
|
494
|
+
const kb = delta - k;
|
|
495
|
+
if (odd && kb >= -(d - 1) && kb <= d - 1 && x + backward[offset + kb] >= n) {
|
|
496
|
+
return [aLo + x0, bLo + y0, aLo + x, bLo + y];
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
for (let k = -d; k <= d; k += 2) {
|
|
500
|
+
let x = k === -d || k !== d && backward[offset + k - 1] < backward[offset + k + 1] ? backward[offset + k + 1] : backward[offset + k - 1] + 1;
|
|
501
|
+
let y = x - k;
|
|
502
|
+
const x0 = x;
|
|
503
|
+
const y0 = y;
|
|
504
|
+
while (x < n && y < m && a[aHi - 1 - x] === b[bHi - 1 - y]) {
|
|
505
|
+
x++;
|
|
506
|
+
y++;
|
|
507
|
+
}
|
|
508
|
+
backward[offset + k] = x;
|
|
509
|
+
const kf = delta - k;
|
|
510
|
+
if (!odd && kf >= -d && kf <= d && x + forward[offset + kf] >= n) {
|
|
511
|
+
return [aHi - x, bHi - y, aHi - x0, bHi - y0];
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
throw new Error("computeLineDiff: no middle snake \u2014 unreachable for differing texts");
|
|
516
|
+
}
|
|
517
|
+
function usePerfBuffer() {
|
|
518
|
+
return useSyncExternalStore(perfStore.subscribe, perfStore.getSnapshot, perfStore.getSnapshot);
|
|
519
|
+
}
|
|
520
|
+
var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
|
|
521
|
+
pushPerfEntry({
|
|
522
|
+
name: `profiler:${id}:${phase}`,
|
|
523
|
+
durationMs: actualDuration,
|
|
524
|
+
ts: commitTime,
|
|
525
|
+
detail: { baseDuration }
|
|
526
|
+
});
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
// src/lib/lessonSegmentUtils.ts
|
|
530
|
+
function parseMarkdownWithCodeBlocks(content) {
|
|
531
|
+
const segments = [];
|
|
532
|
+
const codeBlockRegex = /```([^\n\r]*)\r?\n([\s\S]*?)```/g;
|
|
533
|
+
let lastIndex = 0;
|
|
534
|
+
let match;
|
|
535
|
+
while ((match = codeBlockRegex.exec(content)) !== null) {
|
|
536
|
+
const before = content.slice(lastIndex, match.index);
|
|
537
|
+
if (before.trim()) {
|
|
538
|
+
segments.push({ type: "markdown", content: before });
|
|
539
|
+
}
|
|
540
|
+
const tokens = match[1].trim().split(/\s+/).filter(Boolean);
|
|
541
|
+
let rawLanguage = tokens[0] ?? "text";
|
|
542
|
+
const suffixRunnable = rawLanguage.endsWith("-runnable");
|
|
543
|
+
const runnable = suffixRunnable || tokens.includes("run");
|
|
544
|
+
const baseLanguage = suffixRunnable ? rawLanguage.slice(0, -"-runnable".length) || "text" : rawLanguage;
|
|
545
|
+
segments.push({ type: "code", language: baseLanguage, content: match[2].trim(), runnable });
|
|
546
|
+
lastIndex = codeBlockRegex.lastIndex;
|
|
547
|
+
}
|
|
548
|
+
const remaining = content.slice(lastIndex);
|
|
549
|
+
if (remaining.trim()) {
|
|
550
|
+
segments.push({ type: "markdown", content: remaining });
|
|
551
|
+
}
|
|
552
|
+
return segments;
|
|
553
|
+
}
|
|
554
|
+
function resolveImageUrl(value) {
|
|
555
|
+
if (typeof value === "string") {
|
|
556
|
+
return value;
|
|
557
|
+
}
|
|
558
|
+
if (isFileValue(value)) {
|
|
559
|
+
return value.url;
|
|
560
|
+
}
|
|
561
|
+
return void 0;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// src/lib/parseContentSegments.ts
|
|
565
|
+
function tryParseOrbitalSchema(code) {
|
|
566
|
+
try {
|
|
567
|
+
const parsed = JSON.parse(code);
|
|
568
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
569
|
+
if ("states" in parsed && "transitions" in parsed || Array.isArray(parsed.orbitals)) {
|
|
570
|
+
return parsed;
|
|
571
|
+
}
|
|
572
|
+
} catch {
|
|
573
|
+
}
|
|
574
|
+
return null;
|
|
575
|
+
}
|
|
576
|
+
function parseMarkdownWithCodeBlocks2(content) {
|
|
577
|
+
if (!content) return [];
|
|
578
|
+
const segments = [];
|
|
579
|
+
const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/g;
|
|
580
|
+
let lastIndex = 0;
|
|
581
|
+
let match;
|
|
582
|
+
while ((match = codeBlockRegex.exec(content)) !== null) {
|
|
583
|
+
const before = content.slice(lastIndex, match.index);
|
|
584
|
+
if (before.trim()) {
|
|
585
|
+
segments.push({ type: "markdown", content: before });
|
|
586
|
+
}
|
|
587
|
+
const language = match[1] || "text";
|
|
588
|
+
const code = match[2].trim();
|
|
589
|
+
if (language === "json" || language === "orb") {
|
|
590
|
+
const schema = tryParseOrbitalSchema(code);
|
|
591
|
+
if (schema) {
|
|
592
|
+
segments.push({ type: "orbital", language, content: code, schema });
|
|
593
|
+
lastIndex = codeBlockRegex.lastIndex;
|
|
594
|
+
continue;
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
segments.push({ type: "code", language, content: code });
|
|
598
|
+
lastIndex = codeBlockRegex.lastIndex;
|
|
599
|
+
}
|
|
600
|
+
const remaining = content.slice(lastIndex);
|
|
601
|
+
if (remaining.trim()) {
|
|
602
|
+
segments.push({ type: "markdown", content: remaining });
|
|
603
|
+
}
|
|
604
|
+
return segments;
|
|
605
|
+
}
|
|
606
|
+
function parseContentSegments(content) {
|
|
607
|
+
if (!content) return [];
|
|
608
|
+
const segments = [];
|
|
609
|
+
const tagRegex = /<question>([\s\S]*?)<\/question>\s*<answer>([\s\S]*?)<\/answer>/gi;
|
|
610
|
+
let lastIndex = 0;
|
|
611
|
+
let match;
|
|
612
|
+
while ((match = tagRegex.exec(content)) !== null) {
|
|
613
|
+
const before = content.slice(lastIndex, match.index);
|
|
614
|
+
if (before.trim()) {
|
|
615
|
+
segments.push(...parseMarkdownWithCodeBlocks2(before));
|
|
616
|
+
}
|
|
617
|
+
segments.push({
|
|
618
|
+
type: "quiz",
|
|
619
|
+
question: match[1].trim(),
|
|
620
|
+
answer: match[2].trim()
|
|
621
|
+
});
|
|
622
|
+
lastIndex = tagRegex.lastIndex;
|
|
623
|
+
}
|
|
624
|
+
const remaining = content.slice(lastIndex);
|
|
625
|
+
if (remaining.trim()) {
|
|
626
|
+
segments.push(...parseMarkdownWithCodeBlocks2(remaining));
|
|
627
|
+
}
|
|
628
|
+
return segments;
|
|
629
|
+
}
|
|
630
|
+
var NAMESPACE = "almadar:ui:debug";
|
|
631
|
+
var log = createLogger(NAMESPACE);
|
|
632
|
+
var inputLog = createLogger("almadar:ui:debug:input");
|
|
633
|
+
var collisionLog = createLogger("almadar:ui:debug:collision");
|
|
634
|
+
var physicsLog = createLogger("almadar:ui:debug:physics");
|
|
635
|
+
var gameStateLog = createLogger("almadar:ui:debug:game-state");
|
|
636
|
+
function gateEnabled(level, ns = NAMESPACE) {
|
|
637
|
+
return isLogLevelEnabled(level, ns);
|
|
638
|
+
}
|
|
639
|
+
function isDebugEnabled() {
|
|
640
|
+
return gateEnabled("DEBUG");
|
|
641
|
+
}
|
|
642
|
+
function debug(...args) {
|
|
643
|
+
if (!gateEnabled("DEBUG")) return;
|
|
644
|
+
const [first, ...rest] = args;
|
|
645
|
+
const message = typeof first === "string" ? first : "<debug>";
|
|
646
|
+
if (rest.length === 0 && typeof first === "string") {
|
|
647
|
+
log.debug(message);
|
|
648
|
+
} else {
|
|
649
|
+
log.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
function debugGroup(label) {
|
|
653
|
+
if (gateEnabled("DEBUG")) console.group(`[${NAMESPACE}] ${label}`);
|
|
654
|
+
}
|
|
655
|
+
function debugGroupEnd() {
|
|
656
|
+
if (gateEnabled("DEBUG")) console.groupEnd();
|
|
657
|
+
}
|
|
658
|
+
function debugWarn(...args) {
|
|
659
|
+
if (!gateEnabled("WARN")) return;
|
|
660
|
+
const [first, ...rest] = args;
|
|
661
|
+
const message = typeof first === "string" ? first : "<warn>";
|
|
662
|
+
log.warn(message, rest.length > 0 ? { args: formatArgs(rest) } : void 0);
|
|
663
|
+
}
|
|
664
|
+
function debugError(...args) {
|
|
665
|
+
if (!gateEnabled("ERROR")) return;
|
|
666
|
+
const [first, ...rest] = args;
|
|
667
|
+
const message = typeof first === "string" ? first : "<error>";
|
|
668
|
+
log.error(message, rest.length > 0 ? { args: formatArgs(rest) } : void 0);
|
|
669
|
+
}
|
|
670
|
+
function debugTable(data) {
|
|
671
|
+
if (gateEnabled("DEBUG")) console.table(data);
|
|
672
|
+
}
|
|
673
|
+
function debugTime(label) {
|
|
674
|
+
if (gateEnabled("DEBUG")) console.time(`[${NAMESPACE}] ${label}`);
|
|
675
|
+
}
|
|
676
|
+
function debugTimeEnd(label) {
|
|
677
|
+
if (gateEnabled("DEBUG")) console.timeEnd(`[${NAMESPACE}] ${label}`);
|
|
678
|
+
}
|
|
679
|
+
function debugInput(inputType, data) {
|
|
680
|
+
inputLog.debug(inputType, { data: formatArgs([data]) });
|
|
681
|
+
}
|
|
682
|
+
function debugCollision(entityA, entityB, details) {
|
|
683
|
+
collisionLog.debug("collision", () => ({
|
|
684
|
+
a: entityA.type ?? entityA.id ?? null,
|
|
685
|
+
b: entityB.type ?? entityB.id ?? null,
|
|
686
|
+
details: details === void 0 ? null : formatArgs([details])
|
|
687
|
+
}));
|
|
688
|
+
}
|
|
689
|
+
function debugPhysics(entityId, physics) {
|
|
690
|
+
physicsLog.debug("physics", { entityId, data: formatArgs([physics]) });
|
|
691
|
+
}
|
|
692
|
+
function debugGameState(stateName, value) {
|
|
693
|
+
gameStateLog.debug(stateName, { value: formatArgs([value]) });
|
|
694
|
+
}
|
|
695
|
+
function formatArgs(values) {
|
|
696
|
+
if (values.length === 1) return toLogMetaValue(values[0]);
|
|
697
|
+
return values.map(toLogMetaValue);
|
|
698
|
+
}
|
|
699
|
+
function toLogMetaValue(v) {
|
|
700
|
+
if (v === null || v === void 0) return v;
|
|
701
|
+
if (v instanceof Error) return v;
|
|
702
|
+
const t = typeof v;
|
|
703
|
+
if (t === "string" || t === "number" || t === "boolean") return v;
|
|
704
|
+
if (Array.isArray(v)) return v.map(toLogMetaValue);
|
|
705
|
+
if (t === "object") {
|
|
706
|
+
const out = {};
|
|
707
|
+
for (const [k, val] of Object.entries(v)) {
|
|
708
|
+
out[k] = toLogMetaValue(val);
|
|
709
|
+
}
|
|
710
|
+
return out;
|
|
711
|
+
}
|
|
712
|
+
return String(v);
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
// src/lib/traitRegistry.ts
|
|
716
|
+
var traits = /* @__PURE__ */ new Map();
|
|
717
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
718
|
+
function notifyListeners() {
|
|
719
|
+
listeners.forEach((listener) => listener());
|
|
720
|
+
}
|
|
721
|
+
function registerTrait(info) {
|
|
722
|
+
traits.set(info.id, info);
|
|
723
|
+
notifyListeners();
|
|
724
|
+
}
|
|
725
|
+
function updateTraitState(id, newState) {
|
|
726
|
+
const trait = traits.get(id);
|
|
727
|
+
if (trait) {
|
|
728
|
+
trait.currentState = newState;
|
|
729
|
+
trait.transitionCount++;
|
|
730
|
+
notifyListeners();
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
function updateGuardResult(traitId, guardName, result) {
|
|
734
|
+
const trait = traits.get(traitId);
|
|
735
|
+
if (trait) {
|
|
736
|
+
const guard = trait.guards.find((g) => g.name === guardName);
|
|
737
|
+
if (guard) {
|
|
738
|
+
guard.lastResult = result;
|
|
739
|
+
notifyListeners();
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
function unregisterTrait(id) {
|
|
744
|
+
traits.delete(id);
|
|
745
|
+
notifyListeners();
|
|
746
|
+
}
|
|
747
|
+
function getAllTraits() {
|
|
748
|
+
return Array.from(traits.values());
|
|
749
|
+
}
|
|
750
|
+
function getTrait(id) {
|
|
751
|
+
return traits.get(id);
|
|
752
|
+
}
|
|
753
|
+
function subscribeToTraitChanges(listener) {
|
|
754
|
+
listeners.add(listener);
|
|
755
|
+
return () => listeners.delete(listener);
|
|
756
|
+
}
|
|
757
|
+
function clearTraits() {
|
|
758
|
+
traits.clear();
|
|
759
|
+
notifyListeners();
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
// src/lib/tickRegistry.ts
|
|
763
|
+
var ticks = /* @__PURE__ */ new Map();
|
|
764
|
+
var listeners2 = /* @__PURE__ */ new Set();
|
|
765
|
+
function notifyListeners2() {
|
|
766
|
+
listeners2.forEach((listener) => listener());
|
|
767
|
+
}
|
|
768
|
+
function registerTick(tick) {
|
|
769
|
+
ticks.set(tick.id, tick);
|
|
770
|
+
notifyListeners2();
|
|
771
|
+
}
|
|
772
|
+
function updateTickExecution(id, timestamp) {
|
|
773
|
+
const tick = ticks.get(id);
|
|
774
|
+
if (tick) {
|
|
775
|
+
tick.lastExecuted = timestamp;
|
|
776
|
+
tick.nextExecution = timestamp + tick.interval;
|
|
777
|
+
tick.executionCount++;
|
|
778
|
+
notifyListeners2();
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
function setTickActive(id, isActive) {
|
|
782
|
+
const tick = ticks.get(id);
|
|
783
|
+
if (tick) {
|
|
784
|
+
tick.isActive = isActive;
|
|
785
|
+
notifyListeners2();
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
function unregisterTick(id) {
|
|
789
|
+
ticks.delete(id);
|
|
790
|
+
notifyListeners2();
|
|
791
|
+
}
|
|
792
|
+
function getAllTicks() {
|
|
793
|
+
return Array.from(ticks.values());
|
|
794
|
+
}
|
|
795
|
+
function getTick(id) {
|
|
796
|
+
return ticks.get(id);
|
|
797
|
+
}
|
|
798
|
+
function subscribeToTickChanges(listener) {
|
|
799
|
+
listeners2.add(listener);
|
|
800
|
+
return () => listeners2.delete(listener);
|
|
801
|
+
}
|
|
802
|
+
function clearTicks() {
|
|
803
|
+
ticks.clear();
|
|
804
|
+
notifyListeners2();
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
// src/lib/guardRegistry.ts
|
|
808
|
+
var guardHistory = [];
|
|
809
|
+
var listeners3 = /* @__PURE__ */ new Set();
|
|
810
|
+
var MAX_HISTORY = 100;
|
|
811
|
+
function notifyListeners3() {
|
|
812
|
+
listeners3.forEach((listener) => listener());
|
|
813
|
+
}
|
|
814
|
+
function recordGuardEvaluation(evaluation) {
|
|
815
|
+
const entry = {
|
|
816
|
+
...evaluation,
|
|
817
|
+
id: `guard-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
|
|
818
|
+
timestamp: Date.now()
|
|
819
|
+
};
|
|
820
|
+
guardHistory.unshift(entry);
|
|
821
|
+
if (guardHistory.length > MAX_HISTORY) {
|
|
822
|
+
guardHistory.pop();
|
|
823
|
+
}
|
|
824
|
+
notifyListeners3();
|
|
825
|
+
}
|
|
826
|
+
function getGuardHistory() {
|
|
827
|
+
return [...guardHistory];
|
|
828
|
+
}
|
|
829
|
+
function getRecentGuardEvaluations(count) {
|
|
830
|
+
return guardHistory.slice(0, count);
|
|
831
|
+
}
|
|
832
|
+
function getGuardEvaluationsForTrait(traitName) {
|
|
833
|
+
return guardHistory.filter((g) => g.traitName === traitName);
|
|
834
|
+
}
|
|
835
|
+
function subscribeToGuardChanges(listener) {
|
|
836
|
+
listeners3.add(listener);
|
|
837
|
+
return () => listeners3.delete(listener);
|
|
838
|
+
}
|
|
839
|
+
function clearGuardHistory() {
|
|
840
|
+
guardHistory.length = 0;
|
|
841
|
+
notifyListeners3();
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// src/lib/entityDebug.ts
|
|
845
|
+
var entityProvider = null;
|
|
846
|
+
function setEntityProvider(provider) {
|
|
847
|
+
entityProvider = provider;
|
|
848
|
+
}
|
|
849
|
+
function clearEntityProvider() {
|
|
850
|
+
entityProvider = null;
|
|
851
|
+
}
|
|
852
|
+
function getEntitySnapshot() {
|
|
853
|
+
if (!entityProvider) {
|
|
854
|
+
return null;
|
|
855
|
+
}
|
|
856
|
+
const entities = entityProvider();
|
|
857
|
+
return {
|
|
858
|
+
entities,
|
|
859
|
+
timestamp: Date.now(),
|
|
860
|
+
totalCount: entities.length,
|
|
861
|
+
singletons: {},
|
|
862
|
+
runtime: entities.map((e) => ({ id: e.id, type: e.type, data: e.fields })),
|
|
863
|
+
persistent: {}
|
|
864
|
+
};
|
|
865
|
+
}
|
|
866
|
+
function getEntityById(id) {
|
|
867
|
+
if (!entityProvider) {
|
|
868
|
+
return void 0;
|
|
869
|
+
}
|
|
870
|
+
return entityProvider().find((e) => e.id === id);
|
|
871
|
+
}
|
|
872
|
+
function getEntitiesByType(type) {
|
|
873
|
+
if (!entityProvider) {
|
|
874
|
+
return [];
|
|
875
|
+
}
|
|
876
|
+
return entityProvider().filter((e) => e.type === type);
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
// src/lib/debugRegistry.ts
|
|
880
|
+
var events = [];
|
|
881
|
+
var listeners4 = /* @__PURE__ */ new Set();
|
|
882
|
+
var MAX_EVENTS = 500;
|
|
883
|
+
function notifyListeners4() {
|
|
884
|
+
listeners4.forEach((listener) => listener());
|
|
885
|
+
}
|
|
886
|
+
function logDebugEvent(type, source, message, data) {
|
|
887
|
+
const event = {
|
|
888
|
+
id: `event-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
|
|
889
|
+
type,
|
|
890
|
+
source,
|
|
891
|
+
message,
|
|
892
|
+
data,
|
|
893
|
+
timestamp: Date.now()
|
|
894
|
+
};
|
|
895
|
+
events.unshift(event);
|
|
896
|
+
if (events.length > MAX_EVENTS) {
|
|
897
|
+
events.pop();
|
|
898
|
+
}
|
|
899
|
+
notifyListeners4();
|
|
900
|
+
}
|
|
901
|
+
function logStateChange(source, from, to, event) {
|
|
902
|
+
logDebugEvent("state-change", source, `${from} \u2192 ${to}`, { from, to, event: event ?? null });
|
|
903
|
+
}
|
|
904
|
+
function logEventFired(source, eventName, payload) {
|
|
905
|
+
logDebugEvent("event-fired", source, eventName, { eventName, payload: payload ?? null });
|
|
906
|
+
}
|
|
907
|
+
function logEffectExecuted(source, effectType, details) {
|
|
908
|
+
logDebugEvent("effect-executed", source, effectType, { effectType, details: details ?? null });
|
|
909
|
+
}
|
|
910
|
+
function logError(source, message, error) {
|
|
911
|
+
logDebugEvent("error", source, message, { error: error?.message ?? null });
|
|
912
|
+
}
|
|
913
|
+
function logWarning(source, message, data) {
|
|
914
|
+
logDebugEvent("warning", source, message, data);
|
|
915
|
+
}
|
|
916
|
+
function logInfo(source, message, data) {
|
|
917
|
+
logDebugEvent("info", source, message, data);
|
|
918
|
+
}
|
|
919
|
+
function getDebugEvents() {
|
|
920
|
+
return [...events];
|
|
921
|
+
}
|
|
922
|
+
function getRecentEvents(count) {
|
|
923
|
+
return events.slice(0, count);
|
|
924
|
+
}
|
|
925
|
+
function getEventsByType(type) {
|
|
926
|
+
return events.filter((e) => e.type === type);
|
|
927
|
+
}
|
|
928
|
+
function getEventsBySource(source) {
|
|
929
|
+
return events.filter((e) => e.source === source);
|
|
930
|
+
}
|
|
931
|
+
function subscribeToDebugEvents(listener) {
|
|
932
|
+
listeners4.add(listener);
|
|
933
|
+
return () => listeners4.delete(listener);
|
|
934
|
+
}
|
|
935
|
+
function clearDebugEvents() {
|
|
936
|
+
events.length = 0;
|
|
937
|
+
notifyListeners4();
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
// src/lib/debugUtils.ts
|
|
941
|
+
var DEBUG_STORAGE_KEY = "orbital-debug";
|
|
942
|
+
var listeners5 = /* @__PURE__ */ new Set();
|
|
943
|
+
function isDebugEnabled2() {
|
|
944
|
+
if (typeof window === "undefined") return false;
|
|
945
|
+
return localStorage.getItem(DEBUG_STORAGE_KEY) === "true";
|
|
946
|
+
}
|
|
947
|
+
function setDebugEnabled(enabled) {
|
|
948
|
+
if (typeof window === "undefined") return;
|
|
949
|
+
localStorage.setItem(DEBUG_STORAGE_KEY, String(enabled));
|
|
950
|
+
listeners5.forEach((listener) => listener(enabled));
|
|
951
|
+
}
|
|
952
|
+
function toggleDebug() {
|
|
953
|
+
const newValue = !isDebugEnabled2();
|
|
954
|
+
setDebugEnabled(newValue);
|
|
955
|
+
return newValue;
|
|
956
|
+
}
|
|
957
|
+
function onDebugToggle(listener) {
|
|
958
|
+
listeners5.add(listener);
|
|
959
|
+
return () => listeners5.delete(listener);
|
|
960
|
+
}
|
|
961
|
+
function initDebugShortcut() {
|
|
962
|
+
if (typeof window === "undefined") return () => {
|
|
963
|
+
};
|
|
964
|
+
const handleKeyDown = (e) => {
|
|
965
|
+
if (e.ctrlKey && e.shiftKey && e.key === "D") {
|
|
966
|
+
e.preventDefault();
|
|
967
|
+
toggleDebug();
|
|
968
|
+
}
|
|
969
|
+
};
|
|
970
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
971
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
// src/lib/parseLessonSegments.ts
|
|
975
|
+
function extractTagContent(content, tagName) {
|
|
976
|
+
const closedTagRegex = new RegExp(`<${tagName}>([\\s\\S]*?)<\\/${tagName}>`, "i");
|
|
977
|
+
const closedMatch = content.match(closedTagRegex);
|
|
978
|
+
if (closedMatch) {
|
|
979
|
+
return { content: closedMatch[1].trim(), fullMatch: closedMatch[0] };
|
|
980
|
+
}
|
|
981
|
+
const unclosedTagRegex = new RegExp(
|
|
982
|
+
`<${tagName}>([\\s\\S]*?)(?=<(?:activate|connect|reflect|bloom|prq|question|answer|visualize)|\\n\\n#|$)`,
|
|
983
|
+
"i"
|
|
984
|
+
);
|
|
985
|
+
const unclosedMatch = content.match(unclosedTagRegex);
|
|
986
|
+
if (unclosedMatch) {
|
|
987
|
+
return { content: unclosedMatch[1].trim(), fullMatch: unclosedMatch[0] };
|
|
988
|
+
}
|
|
989
|
+
return null;
|
|
990
|
+
}
|
|
991
|
+
function parseLessonSegments(lesson) {
|
|
992
|
+
if (!lesson) return [];
|
|
993
|
+
let content = lesson.replace(/<prq>[\s\S]*?<\/prq>/gi, "").trim();
|
|
994
|
+
const segments = [];
|
|
995
|
+
const activateResult = extractTagContent(content, "activate");
|
|
996
|
+
if (activateResult) {
|
|
997
|
+
segments.push({ type: "activate", question: activateResult.content });
|
|
998
|
+
content = content.replace(activateResult.fullMatch, "").trim();
|
|
999
|
+
}
|
|
1000
|
+
const connectResult = extractTagContent(content, "connect");
|
|
1001
|
+
if (connectResult) {
|
|
1002
|
+
segments.push({ type: "connect", content: connectResult.content });
|
|
1003
|
+
content = content.replace(connectResult.fullMatch, "").trim();
|
|
1004
|
+
}
|
|
1005
|
+
const tagRegex = new RegExp(
|
|
1006
|
+
'(?<reflect><reflect>(?<reflectClosed>[\\s\\S]*?)<\\/reflect>)|(?<reflectUnclosed><reflect>(?<reflectOpen>[\\s\\S]*?)(?=<(?:activate|connect|reflect|bloom|prq|question|answer|visualize)|\\n\\n#|$))|(?<bloom><bloom\\s+level="(?<bloomLevel>remember|understand|apply|analyze|evaluate|create)">(?<bloomClosed>[\\s\\S]*?)<\\/bloom>)|(?<bloomUnclosed><bloom\\s+level="(?<bloomLevelUn>remember|understand|apply|analyze|evaluate|create)">(?<bloomOpen>[\\s\\S]*?)(?=<(?:activate|connect|reflect|bloom|prq|question|answer|visualize)|\\n\\n#|$))|(?<quiz><question>(?<quizQuestion>[\\s\\S]*?)<\\/question>\\s*<answer>(?<quizAnswer>[\\s\\S]*?)<\\/answer>)|(?<visualize><visualize\\s+type="(?<vizType>algorithms|math|physics|biology|chemistry|probability)"\\s+description="(?<vizDesc>[^"]*?)"\\s*\\/?>)',
|
|
1007
|
+
"gi"
|
|
1008
|
+
);
|
|
1009
|
+
let lastIndex = 0;
|
|
1010
|
+
let match;
|
|
1011
|
+
while ((match = tagRegex.exec(content)) !== null) {
|
|
1012
|
+
const before = content.slice(lastIndex, match.index);
|
|
1013
|
+
if (before.trim()) {
|
|
1014
|
+
segments.push(...parseMarkdownWithCodeBlocks(before));
|
|
1015
|
+
}
|
|
1016
|
+
const g = match.groups ?? {};
|
|
1017
|
+
if (g.reflect || g.reflectUnclosed) {
|
|
1018
|
+
const prompt = (g.reflectClosed ?? g.reflectOpen ?? "").trim();
|
|
1019
|
+
if (prompt) segments.push({ type: "reflect", prompt });
|
|
1020
|
+
} else if (g.bloom || g.bloomUnclosed) {
|
|
1021
|
+
const level = g.bloomLevel ?? g.bloomLevelUn;
|
|
1022
|
+
const bloomContent = g.bloomClosed ?? g.bloomOpen ?? "";
|
|
1023
|
+
if (level && bloomContent) {
|
|
1024
|
+
const qMatch = bloomContent.match(/<question>([\s\S]*?)<\/question>/i);
|
|
1025
|
+
const aMatch = bloomContent.match(/<answer>([\s\S]*?)<\/answer>/i);
|
|
1026
|
+
if (qMatch && aMatch) {
|
|
1027
|
+
segments.push({ type: "bloom", level, question: qMatch[1].trim(), answer: aMatch[1].trim() });
|
|
1028
|
+
} else if (qMatch) {
|
|
1029
|
+
segments.push({ type: "bloom", level, question: qMatch[1].trim(), answer: "(Answer not provided)" });
|
|
1030
|
+
} else {
|
|
1031
|
+
const clean = bloomContent.replace(/^\*\*Question\s*\d*:?\*\*\s*/i, "").replace(/^\*\*Q\d*:?\*\*\s*/i, "").trim();
|
|
1032
|
+
if (clean) segments.push({ type: "bloom", level, question: clean, answer: "(See answers section below)" });
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
} else if (g.quiz) {
|
|
1036
|
+
segments.push({ type: "quiz", question: g.quizQuestion.trim(), answer: g.quizAnswer.trim() });
|
|
1037
|
+
} else if (g.visualize) {
|
|
1038
|
+
segments.push({
|
|
1039
|
+
type: "visualization",
|
|
1040
|
+
visualizationType: g.vizType,
|
|
1041
|
+
description: g.vizDesc ?? ""
|
|
1042
|
+
});
|
|
1043
|
+
}
|
|
1044
|
+
lastIndex = tagRegex.lastIndex;
|
|
1045
|
+
}
|
|
1046
|
+
const remaining = content.slice(lastIndex);
|
|
1047
|
+
if (remaining.trim()) segments.push(...parseMarkdownWithCodeBlocks(remaining));
|
|
1048
|
+
return segments;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
export { EDITOR_MOTIONS, EDITOR_OPERATORS, ENTER_SLOT_CLASS, INDENT_UNIT, MAX_ENTER_DELAY, applyMotion, applyOperator, asEnterAnimation, clearDebugEvents, clearEntityProvider, clearGuardHistory, clearTicks, clearTraits, computeLineDiff, debug, debugCollision, debugError, debugGameState, debugGroup, debugGroupEnd, debugInput, debugPhysics, debugTable, debugTime, debugTimeEnd, debugWarn, enterClassName, getAllTicks, getAllTraits, getDebugEvents, getEntitiesByType, getEntityById, getEntitySnapshot, getEventsBySource, getEventsByType, getGuardEvaluationsForTrait, getGuardHistory, getRecentEvents, getRecentGuardEvaluations, getTick, getTrait, initDebugShortcut, isDebugEnabled, isDebugEnabled2, isEditorMotion, isEditorOperator, logDebugEvent, logEffectExecuted, logError, logEventFired, logInfo, logStateChange, logWarning, motionRange, onDebugToggle, parseContentSegments, parseLessonSegments, parseMarkdownWithCodeBlocks, parseMarkdownWithCodeBlocks2, profilerOnRender, recordGuardEvaluation, registerTick, registerTrait, resolveImageUrl, setDebugEnabled, setEntityProvider, setTickActive, slotPlaysDefaultEnter, subscribeToDebugEvents, subscribeToGuardChanges, subscribeToTickChanges, subscribeToTraitChanges, toggleDebug, unregisterTick, unregisterTrait, updateGuardResult, updateTickExecution, updateTraitState, usePerfBuffer, useSlotEnterRestart };
|