@almadar/ui 5.122.10 → 5.122.12

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.
@@ -9978,6 +9978,22 @@ var init_EmptyState = __esm({
9978
9978
  EmptyState.displayName = "EmptyState";
9979
9979
  }
9980
9980
  });
9981
+ function registerCodeLanguageLoader(loader) {
9982
+ codeLanguageLoader = loader;
9983
+ }
9984
+ function isLanguageRegistered(lang) {
9985
+ return CODE_LANGUAGE_SET.has(lang) || dynamicallyLoaded.has(lang);
9986
+ }
9987
+ async function loadPrismLanguage(lang) {
9988
+ if (isLanguageRegistered(lang)) return;
9989
+ try {
9990
+ const grammar = codeLanguageLoader ? await codeLanguageLoader(lang) : null;
9991
+ if (grammar) SyntaxHighlighter.registerLanguage(lang, grammar);
9992
+ dynamicallyLoaded.add(lang);
9993
+ } catch {
9994
+ dynamicallyLoaded.add(lang);
9995
+ }
9996
+ }
9981
9997
  function computeFoldRegions(code) {
9982
9998
  const lines = code.split("\n");
9983
9999
  const regions = [];
@@ -10013,7 +10029,8 @@ function computeFoldRegions(code) {
10013
10029
  return regions.sort((a, b) => a.start - b.start);
10014
10030
  }
10015
10031
  function toCodeLanguage(value) {
10016
- return value && CODE_LANGUAGE_SET.has(value) ? value : "text";
10032
+ if (!value) return "text";
10033
+ return value.toLowerCase();
10017
10034
  }
10018
10035
  function generateDiff(oldVal, newVal) {
10019
10036
  const oldLines = oldVal.split("\n");
@@ -10032,7 +10049,24 @@ function generateDiff(oldVal, newVal) {
10032
10049
  }
10033
10050
  return diff;
10034
10051
  }
10035
- var orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log4, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, DIFF_STYLE_FALLBACK, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, CodeBlock;
10052
+ function useLanguageReady(language) {
10053
+ const [ready, setReady] = useState(() => isLanguageRegistered(language));
10054
+ useEffect(() => {
10055
+ if (isLanguageRegistered(language)) {
10056
+ if (!ready) setReady(true);
10057
+ return;
10058
+ }
10059
+ let active = true;
10060
+ loadPrismLanguage(language).then(() => {
10061
+ if (active) setReady(true);
10062
+ });
10063
+ return () => {
10064
+ active = false;
10065
+ };
10066
+ }, [language]);
10067
+ return ready;
10068
+ }
10069
+ var dynamicallyLoaded, codeLanguageLoader, orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log4, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, DIFF_STYLE_FALLBACK, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, CodeBlock;
10036
10070
  var init_CodeBlock = __esm({
10037
10071
  "components/core/molecules/markdown/CodeBlock.tsx"() {
10038
10072
  init_cn();
@@ -10073,6 +10107,8 @@ var init_CodeBlock = __esm({
10073
10107
  SyntaxHighlighter.registerLanguage("graphql", langGraphql);
10074
10108
  SyntaxHighlighter.registerLanguage("orb", orbLanguage);
10075
10109
  SyntaxHighlighter.registerLanguage("lolo", loloLanguage);
10110
+ dynamicallyLoaded = /* @__PURE__ */ new Set();
10111
+ codeLanguageLoader = null;
10076
10112
  orbStyleOverrides = {
10077
10113
  "orb-binding": { color: ORB_COLORS.dark.binding, fontWeight: "bold" },
10078
10114
  "orb-effect": { color: ORB_COLORS.dark.effect, fontWeight: "bold" },
@@ -10188,6 +10224,7 @@ var init_CodeBlock = __esm({
10188
10224
  const isOrb = language === "orb";
10189
10225
  const isLolo = language === "lolo";
10190
10226
  const activeStyle = isOrb ? orbStyle : isLolo ? loloStyle : dark;
10227
+ const languageReady = useLanguageReady(language);
10191
10228
  const eventBus = useEventBus();
10192
10229
  const { t } = useTranslate();
10193
10230
  const scrollRef = useRef(null);
@@ -10311,7 +10348,7 @@ var init_CodeBlock = __esm({
10311
10348
  children: code
10312
10349
  }
10313
10350
  ),
10314
- [code, language, activeStyle]
10351
+ [code, language, activeStyle, languageReady]
10315
10352
  );
10316
10353
  useLayoutEffect(() => {
10317
10354
  const container = codeRef.current;
@@ -10911,10 +10948,10 @@ var init_MarkdownContent = __esm({
10911
10948
  }
10912
10949
  });
10913
10950
 
10914
- // components/core/molecules/lessonSegmentUtils.ts
10951
+ // lib/lessonSegmentUtils.ts
10915
10952
  function parseMarkdownWithCodeBlocks(content) {
10916
10953
  const segments = [];
10917
- const codeBlockRegex = /```([\w-]+)?(?:\s+(run))?\n([\s\S]*?)```/g;
10954
+ const codeBlockRegex = /```([^\n\r]*)\r?\n([\s\S]*?)```/g;
10918
10955
  let lastIndex = 0;
10919
10956
  let match;
10920
10957
  while ((match = codeBlockRegex.exec(content)) !== null) {
@@ -10922,12 +10959,12 @@ function parseMarkdownWithCodeBlocks(content) {
10922
10959
  if (before.trim()) {
10923
10960
  segments.push({ type: "markdown", content: before });
10924
10961
  }
10925
- const rawLanguage = match[1] ?? "text";
10926
- const runModifier = !!match[2];
10962
+ const tokens = match[1].trim().split(/\s+/).filter(Boolean);
10963
+ let rawLanguage = tokens[0] ?? "text";
10927
10964
  const suffixRunnable = rawLanguage.endsWith("-runnable");
10928
- const runnable = runModifier || suffixRunnable;
10965
+ const runnable = suffixRunnable || tokens.includes("run");
10929
10966
  const baseLanguage = suffixRunnable ? rawLanguage.slice(0, -"-runnable".length) || "text" : rawLanguage;
10930
- segments.push({ type: "code", language: baseLanguage, content: match[3].trim(), runnable });
10967
+ segments.push({ type: "code", language: baseLanguage, content: match[2].trim(), runnable });
10931
10968
  lastIndex = codeBlockRegex.lastIndex;
10932
10969
  }
10933
10970
  const remaining = content.slice(lastIndex);
@@ -10937,7 +10974,7 @@ function parseMarkdownWithCodeBlocks(content) {
10937
10974
  return segments;
10938
10975
  }
10939
10976
  var init_lessonSegmentUtils = __esm({
10940
- "components/core/molecules/lessonSegmentUtils.ts"() {
10977
+ "lib/lessonSegmentUtils.ts"() {
10941
10978
  }
10942
10979
  });
10943
10980
  var BLOOM_CONFIG, BloomQuizBlock;
@@ -37534,7 +37571,7 @@ var init_ReflectionBlock = __esm({
37534
37571
  }
37535
37572
  });
37536
37573
 
37537
- // components/core/molecules/parseLessonSegments.ts
37574
+ // lib/parseLessonSegments.ts
37538
37575
  function extractTagContent(content, tagName) {
37539
37576
  const closedTagRegex = new RegExp(`<${tagName}>([\\s\\S]*?)<\\/${tagName}>`, "i");
37540
37577
  const closedMatch = content.match(closedTagRegex);
@@ -37611,7 +37648,7 @@ function parseLessonSegments(lesson) {
37611
37648
  return segments;
37612
37649
  }
37613
37650
  var init_parseLessonSegments = __esm({
37614
- "components/core/molecules/parseLessonSegments.ts"() {
37651
+ "lib/parseLessonSegments.ts"() {
37615
37652
  init_lessonSegmentUtils();
37616
37653
  }
37617
37654
  });
@@ -48245,4 +48282,4 @@ function useGitHubBranches(owner, repo, enabled = true) {
48245
48282
  });
48246
48283
  }
48247
48284
 
48248
- export { ALL_PRESETS, ALMADAR_DND_MIME, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, Card2 as ActionCard, ActionPalette, ActionTile, ActivationBlock, Alert, AlgorithmCanvas, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, AssetPicker, AtlasImage, AtlasPanel, AuthLayout, Avatar, Badge, BehaviorView, BiologyCanvas, BloomQuizBlock, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, BranchingLogicBuilder, Breadcrumb, Button, ButtonGroup, CTABanner, CalendarGrid, Canvas, Canvas2D, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CaseStudyCard, CaseStudyOrganism, Center, Chart, ChartLegend, ChatBar, Checkbox, ChemistryCanvas, ChoiceButton, Coachmark, CodeBlock, CodeRunnerPanel, CollapsibleSection, CommunityLinks, ConditionalWrapper, ConfettiEffect, ConfirmDialog, ConnectionBlock, Container, ContentRenderer, ContentSection, ControlButton, ControlGrid, CounterTemplate, DEFAULT_LIKERT_OPTIONS, DEFAULT_MATRIX_COLUMNS, DEFAULT_SLOTS, DIAMOND_TOP_Y, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangePicker, DateRangeSelector, DayCell, DetailPanel, Dialog, DialogueBubble, Divider, DocBreadcrumb, DocPagination, DocSearch, DocSidebar, DocTOC, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, ELEMENT_SELECTED_EVENT, EdgeDecoration, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EmptyState, EntityDisplayEvents, ErrorBoundary, ErrorState, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FeatureCard, FeatureDetailPageTemplate, FeatureGrid, FeatureGridOrganism, FileTree, FilterGroup, FilterPill, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormActions, FormField, FormLayout, FormSection, FormSectionHeader, GameAudioToggle, GameHud, GameIcon, GameMenu, GameShell, GenericAppTemplate, GeometricPattern, GradientDivider, GraphCanvas, GraphView, Grid, GridPicker, HStack, Header, HealthBar, HeroOrganism, HeroSection, I18nProvider, IDENTITY_BOOK_FIELDS, Icon, IconPicker, InfiniteScrollSentinel, Input, InputGroup, InstallBox, JazariStateMachine, JsonTreeEditor, Label, LandingPageTemplate, LawReferenceTooltip, LearningCanvas, Lightbox, LikertScale, LineChart2 as LineChart, List3 as List, LoadingState, MapView, MarkdownContent, MarketingFooter, MarketingStatCard, MasterDetail, MasterDetailLayout, MathCanvas, MatrixQuestion, MediaGallery, Menu, Meter, Modal, ModalSlot, ModuleCard, Navigation, NodeSlotEditor, NotifyListener, NumberStepper, OnboardingSpotlight, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, PageTransition, Pagination, PatternTile, PhysicsCanvas, Popover, PositionedCanvas, Presence, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, PropertyInspector, PullQuote, PullToRefresh, QrScanner, QuizBlock, Radio, RangeSlider, ReflectionBlock, RelationSelect, RepeatableFormSection, ReplyTree, RichBlockEditor, RuntimeDebugger, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, ScaledDiagram, ScoreDisplay, SearchInput, Section, SectionHeader, SegmentRenderer, Select, SequenceBar, ServiceCatalog, SharedEntityStoreContext, ShowcaseCard, ShowcaseOrganism, SidePanel, Sidebar, SignaturePad, SimpleGrid, Skeleton, SlotContentRenderer, SocialProof, SortableList, Spacer, Sparkline, Spinner, Split, SplitPane, SplitSection, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateGraph, StateJsonView, StateMachineView, StateNode2 as StateNode, StatsGrid, StatsOrganism, StatusBar, StatusDot, StepFlow, StepFlowOrganism, SubagentTracePanel, SvgBranch, SvgConnection, SvgFlow, SvgGrid, SvgLobe, SvgMesh, SvgMorph, SvgNode, SvgPulse, SvgRing, SvgShield, SvgStack, SwipeableRow, Switch, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, TableView, Tabs, TagCloud, TagInput, TeamCard, TeamOrganism, TerrainPalette, TextHighlight, Textarea, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitFrame, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UploadDropZone, VStack, VersionDiff, ViolationAlert, VoteStack, WizardContainer, WizardNavigation, WizardProgress, boardEntity, bool, calculateAttackTargets, calculateValidMoves, cn, createInitialGameState, createSharedEntityStore, createTranslate, createUnitAnimationState, getCurrentFrame, getTileDimensions, inferDirection, isoToScreen, makeAsset, makeAssetMap, mapBookData, num, objAvailableActions, objAvailableEvents, objCurrentState, objIcon, objId, objMaxRules, objName, objRules, objStates, parseEditFocus, parseLessonSegments, parseMarkdownWithCodeBlocks, parseQueryBinding, pendulum, projectileMotion, resolveFieldMap, resolveFrame, resolveSheetDirection, rows, runTickFrame, screenToIso, springOscillator, str, tickAnimationState, toCodeLanguage, transitionAnimation, unitHealth, unitPosition, unitTeam, useAgentChat, useAnchorRect, useAtlasSliceDataUrl, useAuthContext, useCamera, useCanvasGestures, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useEmitEvent, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGameAudio, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useImageCache, useInfiniteScroll, useLongPress, useOrbitalHistory, usePresence, usePreview, usePullToRefresh, useQuerySingleton, useRenderInterpolation, useSharedEntitySnapshot, useSharedEntityStore, useSharedEntityStoreContext, useSwipeGesture, useTapReveal, useTraitListens, useTranslate115 as useTranslate, useUIEvents, useUISlotManager, useUnitSpriteAtlas, useValidation, vec2 };
48285
+ export { ALL_PRESETS, ALMADAR_DND_MIME, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, Card2 as ActionCard, ActionPalette, ActionTile, ActivationBlock, Alert, AlgorithmCanvas, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, AssetPicker, AtlasImage, AtlasPanel, AuthLayout, Avatar, Badge, BehaviorView, BiologyCanvas, BloomQuizBlock, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, BranchingLogicBuilder, Breadcrumb, Button, ButtonGroup, CTABanner, CalendarGrid, Canvas, Canvas2D, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CaseStudyCard, CaseStudyOrganism, Center, Chart, ChartLegend, ChatBar, Checkbox, ChemistryCanvas, ChoiceButton, Coachmark, CodeBlock, CodeRunnerPanel, CollapsibleSection, CommunityLinks, ConditionalWrapper, ConfettiEffect, ConfirmDialog, ConnectionBlock, Container, ContentRenderer, ContentSection, ControlButton, ControlGrid, CounterTemplate, DEFAULT_LIKERT_OPTIONS, DEFAULT_MATRIX_COLUMNS, DEFAULT_SLOTS, DIAMOND_TOP_Y, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangePicker, DateRangeSelector, DayCell, DetailPanel, Dialog, DialogueBubble, Divider, DocBreadcrumb, DocPagination, DocSearch, DocSidebar, DocTOC, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, ELEMENT_SELECTED_EVENT, EdgeDecoration, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EmptyState, EntityDisplayEvents, ErrorBoundary, ErrorState, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FeatureCard, FeatureDetailPageTemplate, FeatureGrid, FeatureGridOrganism, FileTree, FilterGroup, FilterPill, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormActions, FormField, FormLayout, FormSection, FormSectionHeader, GameAudioToggle, GameHud, GameIcon, GameMenu, GameShell, GenericAppTemplate, GeometricPattern, GradientDivider, GraphCanvas, GraphView, Grid, GridPicker, HStack, Header, HealthBar, HeroOrganism, HeroSection, I18nProvider, IDENTITY_BOOK_FIELDS, Icon, IconPicker, InfiniteScrollSentinel, Input, InputGroup, InstallBox, JazariStateMachine, JsonTreeEditor, Label, LandingPageTemplate, LawReferenceTooltip, LearningCanvas, Lightbox, LikertScale, LineChart2 as LineChart, List3 as List, LoadingState, MapView, MarkdownContent, MarketingFooter, MarketingStatCard, MasterDetail, MasterDetailLayout, MathCanvas, MatrixQuestion, MediaGallery, Menu, Meter, Modal, ModalSlot, ModuleCard, Navigation, NodeSlotEditor, NotifyListener, NumberStepper, OnboardingSpotlight, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, PageTransition, Pagination, PatternTile, PhysicsCanvas, Popover, PositionedCanvas, Presence, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, PropertyInspector, PullQuote, PullToRefresh, QrScanner, QuizBlock, Radio, RangeSlider, ReflectionBlock, RelationSelect, RepeatableFormSection, ReplyTree, RichBlockEditor, RuntimeDebugger, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, ScaledDiagram, ScoreDisplay, SearchInput, Section, SectionHeader, SegmentRenderer, Select, SequenceBar, ServiceCatalog, SharedEntityStoreContext, ShowcaseCard, ShowcaseOrganism, SidePanel, Sidebar, SignaturePad, SimpleGrid, Skeleton, SlotContentRenderer, SocialProof, SortableList, Spacer, Sparkline, Spinner, Split, SplitPane, SplitSection, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateGraph, StateJsonView, StateMachineView, StateNode2 as StateNode, StatsGrid, StatsOrganism, StatusBar, StatusDot, StepFlow, StepFlowOrganism, SubagentTracePanel, SvgBranch, SvgConnection, SvgFlow, SvgGrid, SvgLobe, SvgMesh, SvgMorph, SvgNode, SvgPulse, SvgRing, SvgShield, SvgStack, SwipeableRow, Switch, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, TableView, Tabs, TagCloud, TagInput, TeamCard, TeamOrganism, TerrainPalette, TextHighlight, Textarea, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitFrame, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UploadDropZone, VStack, VersionDiff, ViolationAlert, VoteStack, WizardContainer, WizardNavigation, WizardProgress, boardEntity, bool, calculateAttackTargets, calculateValidMoves, cn, createInitialGameState, createSharedEntityStore, createTranslate, createUnitAnimationState, getCurrentFrame, getTileDimensions, inferDirection, isoToScreen, makeAsset, makeAssetMap, mapBookData, num, objAvailableActions, objAvailableEvents, objCurrentState, objIcon, objId, objMaxRules, objName, objRules, objStates, parseEditFocus, parseLessonSegments, parseMarkdownWithCodeBlocks, parseQueryBinding, pendulum, projectileMotion, registerCodeLanguageLoader, resolveFieldMap, resolveFrame, resolveSheetDirection, rows, runTickFrame, screenToIso, springOscillator, str, tickAnimationState, toCodeLanguage, transitionAnimation, unitHealth, unitPosition, unitTeam, useAgentChat, useAnchorRect, useAtlasSliceDataUrl, useAuthContext, useCamera, useCanvasGestures, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useEmitEvent, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGameAudio, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useImageCache, useInfiniteScroll, useLongPress, useOrbitalHistory, usePresence, usePreview, usePullToRefresh, useQuerySingleton, useRenderInterpolation, useSharedEntitySnapshot, useSharedEntityStore, useSharedEntityStoreContext, useSwipeGesture, useTapReveal, useTraitListens, useTranslate115 as useTranslate, useUIEvents, useUISlotManager, useUnitSpriteAtlas, useValidation, vec2 };
@@ -14414,6 +14414,19 @@ var init_EmptyState = __esm({
14414
14414
  EmptyState.displayName = "EmptyState";
14415
14415
  }
14416
14416
  });
14417
+ function isLanguageRegistered(lang) {
14418
+ return CODE_LANGUAGE_SET.has(lang) || dynamicallyLoaded.has(lang);
14419
+ }
14420
+ async function loadPrismLanguage(lang) {
14421
+ if (isLanguageRegistered(lang)) return;
14422
+ try {
14423
+ const grammar = codeLanguageLoader ? await codeLanguageLoader(lang) : null;
14424
+ if (grammar) SyntaxHighlighter__default.default.registerLanguage(lang, grammar);
14425
+ dynamicallyLoaded.add(lang);
14426
+ } catch {
14427
+ dynamicallyLoaded.add(lang);
14428
+ }
14429
+ }
14417
14430
  function computeFoldRegions(code) {
14418
14431
  const lines = code.split("\n");
14419
14432
  const regions = [];
@@ -14449,7 +14462,8 @@ function computeFoldRegions(code) {
14449
14462
  return regions.sort((a, b) => a.start - b.start);
14450
14463
  }
14451
14464
  function toCodeLanguage(value) {
14452
- return value && CODE_LANGUAGE_SET.has(value) ? value : "text";
14465
+ if (!value) return "text";
14466
+ return value.toLowerCase();
14453
14467
  }
14454
14468
  function generateDiff(oldVal, newVal) {
14455
14469
  const oldLines = oldVal.split("\n");
@@ -14468,7 +14482,24 @@ function generateDiff(oldVal, newVal) {
14468
14482
  }
14469
14483
  return diff;
14470
14484
  }
14471
- var orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log7, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, DIFF_STYLE_FALLBACK, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, CodeBlock;
14485
+ function useLanguageReady(language) {
14486
+ const [ready, setReady] = React84.useState(() => isLanguageRegistered(language));
14487
+ React84.useEffect(() => {
14488
+ if (isLanguageRegistered(language)) {
14489
+ if (!ready) setReady(true);
14490
+ return;
14491
+ }
14492
+ let active = true;
14493
+ loadPrismLanguage(language).then(() => {
14494
+ if (active) setReady(true);
14495
+ });
14496
+ return () => {
14497
+ active = false;
14498
+ };
14499
+ }, [language]);
14500
+ return ready;
14501
+ }
14502
+ var dynamicallyLoaded, codeLanguageLoader, orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log7, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, DIFF_STYLE_FALLBACK, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, CodeBlock;
14472
14503
  var init_CodeBlock = __esm({
14473
14504
  "components/core/molecules/markdown/CodeBlock.tsx"() {
14474
14505
  init_cn();
@@ -14509,6 +14540,8 @@ var init_CodeBlock = __esm({
14509
14540
  SyntaxHighlighter__default.default.registerLanguage("graphql", langGraphql__default.default);
14510
14541
  SyntaxHighlighter__default.default.registerLanguage("orb", syntax.orbLanguage);
14511
14542
  SyntaxHighlighter__default.default.registerLanguage("lolo", syntax.loloLanguage);
14543
+ dynamicallyLoaded = /* @__PURE__ */ new Set();
14544
+ codeLanguageLoader = null;
14512
14545
  orbStyleOverrides = {
14513
14546
  "orb-binding": { color: syntax.ORB_COLORS.dark.binding, fontWeight: "bold" },
14514
14547
  "orb-effect": { color: syntax.ORB_COLORS.dark.effect, fontWeight: "bold" },
@@ -14624,6 +14657,7 @@ var init_CodeBlock = __esm({
14624
14657
  const isOrb = language === "orb";
14625
14658
  const isLolo = language === "lolo";
14626
14659
  const activeStyle = isOrb ? orbStyle : isLolo ? loloStyle : dark__default.default;
14660
+ const languageReady = useLanguageReady(language);
14627
14661
  const eventBus = useEventBus();
14628
14662
  const { t } = hooks.useTranslate();
14629
14663
  const scrollRef = React84.useRef(null);
@@ -14747,7 +14781,7 @@ var init_CodeBlock = __esm({
14747
14781
  children: code
14748
14782
  }
14749
14783
  ),
14750
- [code, language, activeStyle]
14784
+ [code, language, activeStyle, languageReady]
14751
14785
  );
14752
14786
  React84.useLayoutEffect(() => {
14753
14787
  const container = codeRef.current;
@@ -15347,10 +15381,10 @@ var init_MarkdownContent = __esm({
15347
15381
  }
15348
15382
  });
15349
15383
 
15350
- // components/core/molecules/lessonSegmentUtils.ts
15384
+ // lib/lessonSegmentUtils.ts
15351
15385
  function parseMarkdownWithCodeBlocks(content) {
15352
15386
  const segments = [];
15353
- const codeBlockRegex = /```([\w-]+)?(?:\s+(run))?\n([\s\S]*?)```/g;
15387
+ const codeBlockRegex = /```([^\n\r]*)\r?\n([\s\S]*?)```/g;
15354
15388
  let lastIndex = 0;
15355
15389
  let match;
15356
15390
  while ((match = codeBlockRegex.exec(content)) !== null) {
@@ -15358,12 +15392,12 @@ function parseMarkdownWithCodeBlocks(content) {
15358
15392
  if (before.trim()) {
15359
15393
  segments.push({ type: "markdown", content: before });
15360
15394
  }
15361
- const rawLanguage = match[1] ?? "text";
15362
- const runModifier = !!match[2];
15395
+ const tokens = match[1].trim().split(/\s+/).filter(Boolean);
15396
+ let rawLanguage = tokens[0] ?? "text";
15363
15397
  const suffixRunnable = rawLanguage.endsWith("-runnable");
15364
- const runnable = runModifier || suffixRunnable;
15398
+ const runnable = suffixRunnable || tokens.includes("run");
15365
15399
  const baseLanguage = suffixRunnable ? rawLanguage.slice(0, -"-runnable".length) || "text" : rawLanguage;
15366
- segments.push({ type: "code", language: baseLanguage, content: match[3].trim(), runnable });
15400
+ segments.push({ type: "code", language: baseLanguage, content: match[2].trim(), runnable });
15367
15401
  lastIndex = codeBlockRegex.lastIndex;
15368
15402
  }
15369
15403
  const remaining = content.slice(lastIndex);
@@ -15373,7 +15407,7 @@ function parseMarkdownWithCodeBlocks(content) {
15373
15407
  return segments;
15374
15408
  }
15375
15409
  var init_lessonSegmentUtils = __esm({
15376
- "components/core/molecules/lessonSegmentUtils.ts"() {
15410
+ "lib/lessonSegmentUtils.ts"() {
15377
15411
  }
15378
15412
  });
15379
15413
  var BLOOM_CONFIG, BloomQuizBlock;
@@ -14369,6 +14369,19 @@ var init_EmptyState = __esm({
14369
14369
  EmptyState.displayName = "EmptyState";
14370
14370
  }
14371
14371
  });
14372
+ function isLanguageRegistered(lang) {
14373
+ return CODE_LANGUAGE_SET.has(lang) || dynamicallyLoaded.has(lang);
14374
+ }
14375
+ async function loadPrismLanguage(lang) {
14376
+ if (isLanguageRegistered(lang)) return;
14377
+ try {
14378
+ const grammar = codeLanguageLoader ? await codeLanguageLoader(lang) : null;
14379
+ if (grammar) SyntaxHighlighter.registerLanguage(lang, grammar);
14380
+ dynamicallyLoaded.add(lang);
14381
+ } catch {
14382
+ dynamicallyLoaded.add(lang);
14383
+ }
14384
+ }
14372
14385
  function computeFoldRegions(code) {
14373
14386
  const lines = code.split("\n");
14374
14387
  const regions = [];
@@ -14404,7 +14417,8 @@ function computeFoldRegions(code) {
14404
14417
  return regions.sort((a, b) => a.start - b.start);
14405
14418
  }
14406
14419
  function toCodeLanguage(value) {
14407
- return value && CODE_LANGUAGE_SET.has(value) ? value : "text";
14420
+ if (!value) return "text";
14421
+ return value.toLowerCase();
14408
14422
  }
14409
14423
  function generateDiff(oldVal, newVal) {
14410
14424
  const oldLines = oldVal.split("\n");
@@ -14423,7 +14437,24 @@ function generateDiff(oldVal, newVal) {
14423
14437
  }
14424
14438
  return diff;
14425
14439
  }
14426
- var orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log7, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, DIFF_STYLE_FALLBACK, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, CodeBlock;
14440
+ function useLanguageReady(language) {
14441
+ const [ready, setReady] = useState(() => isLanguageRegistered(language));
14442
+ useEffect(() => {
14443
+ if (isLanguageRegistered(language)) {
14444
+ if (!ready) setReady(true);
14445
+ return;
14446
+ }
14447
+ let active = true;
14448
+ loadPrismLanguage(language).then(() => {
14449
+ if (active) setReady(true);
14450
+ });
14451
+ return () => {
14452
+ active = false;
14453
+ };
14454
+ }, [language]);
14455
+ return ready;
14456
+ }
14457
+ var dynamicallyLoaded, codeLanguageLoader, orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log7, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, DIFF_STYLE_FALLBACK, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, CodeBlock;
14427
14458
  var init_CodeBlock = __esm({
14428
14459
  "components/core/molecules/markdown/CodeBlock.tsx"() {
14429
14460
  init_cn();
@@ -14464,6 +14495,8 @@ var init_CodeBlock = __esm({
14464
14495
  SyntaxHighlighter.registerLanguage("graphql", langGraphql);
14465
14496
  SyntaxHighlighter.registerLanguage("orb", orbLanguage);
14466
14497
  SyntaxHighlighter.registerLanguage("lolo", loloLanguage);
14498
+ dynamicallyLoaded = /* @__PURE__ */ new Set();
14499
+ codeLanguageLoader = null;
14467
14500
  orbStyleOverrides = {
14468
14501
  "orb-binding": { color: ORB_COLORS.dark.binding, fontWeight: "bold" },
14469
14502
  "orb-effect": { color: ORB_COLORS.dark.effect, fontWeight: "bold" },
@@ -14579,6 +14612,7 @@ var init_CodeBlock = __esm({
14579
14612
  const isOrb = language === "orb";
14580
14613
  const isLolo = language === "lolo";
14581
14614
  const activeStyle = isOrb ? orbStyle : isLolo ? loloStyle : dark;
14615
+ const languageReady = useLanguageReady(language);
14582
14616
  const eventBus = useEventBus();
14583
14617
  const { t } = useTranslate();
14584
14618
  const scrollRef = useRef(null);
@@ -14702,7 +14736,7 @@ var init_CodeBlock = __esm({
14702
14736
  children: code
14703
14737
  }
14704
14738
  ),
14705
- [code, language, activeStyle]
14739
+ [code, language, activeStyle, languageReady]
14706
14740
  );
14707
14741
  useLayoutEffect(() => {
14708
14742
  const container = codeRef.current;
@@ -15302,10 +15336,10 @@ var init_MarkdownContent = __esm({
15302
15336
  }
15303
15337
  });
15304
15338
 
15305
- // components/core/molecules/lessonSegmentUtils.ts
15339
+ // lib/lessonSegmentUtils.ts
15306
15340
  function parseMarkdownWithCodeBlocks(content) {
15307
15341
  const segments = [];
15308
- const codeBlockRegex = /```([\w-]+)?(?:\s+(run))?\n([\s\S]*?)```/g;
15342
+ const codeBlockRegex = /```([^\n\r]*)\r?\n([\s\S]*?)```/g;
15309
15343
  let lastIndex = 0;
15310
15344
  let match;
15311
15345
  while ((match = codeBlockRegex.exec(content)) !== null) {
@@ -15313,12 +15347,12 @@ function parseMarkdownWithCodeBlocks(content) {
15313
15347
  if (before.trim()) {
15314
15348
  segments.push({ type: "markdown", content: before });
15315
15349
  }
15316
- const rawLanguage = match[1] ?? "text";
15317
- const runModifier = !!match[2];
15350
+ const tokens = match[1].trim().split(/\s+/).filter(Boolean);
15351
+ let rawLanguage = tokens[0] ?? "text";
15318
15352
  const suffixRunnable = rawLanguage.endsWith("-runnable");
15319
- const runnable = runModifier || suffixRunnable;
15353
+ const runnable = suffixRunnable || tokens.includes("run");
15320
15354
  const baseLanguage = suffixRunnable ? rawLanguage.slice(0, -"-runnable".length) || "text" : rawLanguage;
15321
- segments.push({ type: "code", language: baseLanguage, content: match[3].trim(), runnable });
15355
+ segments.push({ type: "code", language: baseLanguage, content: match[2].trim(), runnable });
15322
15356
  lastIndex = codeBlockRegex.lastIndex;
15323
15357
  }
15324
15358
  const remaining = content.slice(lastIndex);
@@ -15328,7 +15362,7 @@ function parseMarkdownWithCodeBlocks(content) {
15328
15362
  return segments;
15329
15363
  }
15330
15364
  var init_lessonSegmentUtils = __esm({
15331
- "components/core/molecules/lessonSegmentUtils.ts"() {
15365
+ "lib/lessonSegmentUtils.ts"() {
15332
15366
  }
15333
15367
  });
15334
15368
  var BLOOM_CONFIG, BloomQuizBlock;
@@ -14099,6 +14099,19 @@ var init_EmptyState = __esm({
14099
14099
  EmptyState.displayName = "EmptyState";
14100
14100
  }
14101
14101
  });
14102
+ function isLanguageRegistered(lang) {
14103
+ return CODE_LANGUAGE_SET.has(lang) || dynamicallyLoaded.has(lang);
14104
+ }
14105
+ async function loadPrismLanguage(lang) {
14106
+ if (isLanguageRegistered(lang)) return;
14107
+ try {
14108
+ const grammar = codeLanguageLoader ? await codeLanguageLoader(lang) : null;
14109
+ if (grammar) SyntaxHighlighter__default.default.registerLanguage(lang, grammar);
14110
+ dynamicallyLoaded.add(lang);
14111
+ } catch {
14112
+ dynamicallyLoaded.add(lang);
14113
+ }
14114
+ }
14102
14115
  function computeFoldRegions(code) {
14103
14116
  const lines = code.split("\n");
14104
14117
  const regions = [];
@@ -14134,7 +14147,8 @@ function computeFoldRegions(code) {
14134
14147
  return regions.sort((a, b) => a.start - b.start);
14135
14148
  }
14136
14149
  function toCodeLanguage(value) {
14137
- return value && CODE_LANGUAGE_SET.has(value) ? value : "text";
14150
+ if (!value) return "text";
14151
+ return value.toLowerCase();
14138
14152
  }
14139
14153
  function generateDiff(oldVal, newVal) {
14140
14154
  const oldLines = oldVal.split("\n");
@@ -14153,7 +14167,24 @@ function generateDiff(oldVal, newVal) {
14153
14167
  }
14154
14168
  return diff;
14155
14169
  }
14156
- var orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log6, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, DIFF_STYLE_FALLBACK, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, CodeBlock;
14170
+ function useLanguageReady(language) {
14171
+ const [ready, setReady] = React82.useState(() => isLanguageRegistered(language));
14172
+ React82.useEffect(() => {
14173
+ if (isLanguageRegistered(language)) {
14174
+ if (!ready) setReady(true);
14175
+ return;
14176
+ }
14177
+ let active = true;
14178
+ loadPrismLanguage(language).then(() => {
14179
+ if (active) setReady(true);
14180
+ });
14181
+ return () => {
14182
+ active = false;
14183
+ };
14184
+ }, [language]);
14185
+ return ready;
14186
+ }
14187
+ var dynamicallyLoaded, codeLanguageLoader, orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log6, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, DIFF_STYLE_FALLBACK, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, CodeBlock;
14157
14188
  var init_CodeBlock = __esm({
14158
14189
  "components/core/molecules/markdown/CodeBlock.tsx"() {
14159
14190
  init_cn();
@@ -14194,6 +14225,8 @@ var init_CodeBlock = __esm({
14194
14225
  SyntaxHighlighter__default.default.registerLanguage("graphql", langGraphql__default.default);
14195
14226
  SyntaxHighlighter__default.default.registerLanguage("orb", syntax.orbLanguage);
14196
14227
  SyntaxHighlighter__default.default.registerLanguage("lolo", syntax.loloLanguage);
14228
+ dynamicallyLoaded = /* @__PURE__ */ new Set();
14229
+ codeLanguageLoader = null;
14197
14230
  orbStyleOverrides = {
14198
14231
  "orb-binding": { color: syntax.ORB_COLORS.dark.binding, fontWeight: "bold" },
14199
14232
  "orb-effect": { color: syntax.ORB_COLORS.dark.effect, fontWeight: "bold" },
@@ -14309,6 +14342,7 @@ var init_CodeBlock = __esm({
14309
14342
  const isOrb = language === "orb";
14310
14343
  const isLolo = language === "lolo";
14311
14344
  const activeStyle = isOrb ? orbStyle : isLolo ? loloStyle : dark__default.default;
14345
+ const languageReady = useLanguageReady(language);
14312
14346
  const eventBus = useEventBus();
14313
14347
  const { t } = hooks.useTranslate();
14314
14348
  const scrollRef = React82.useRef(null);
@@ -14432,7 +14466,7 @@ var init_CodeBlock = __esm({
14432
14466
  children: code
14433
14467
  }
14434
14468
  ),
14435
- [code, language, activeStyle]
14469
+ [code, language, activeStyle, languageReady]
14436
14470
  );
14437
14471
  React82.useLayoutEffect(() => {
14438
14472
  const container = codeRef.current;
@@ -15032,10 +15066,10 @@ var init_MarkdownContent = __esm({
15032
15066
  }
15033
15067
  });
15034
15068
 
15035
- // components/core/molecules/lessonSegmentUtils.ts
15069
+ // lib/lessonSegmentUtils.ts
15036
15070
  function parseMarkdownWithCodeBlocks(content) {
15037
15071
  const segments = [];
15038
- const codeBlockRegex = /```([\w-]+)?(?:\s+(run))?\n([\s\S]*?)```/g;
15072
+ const codeBlockRegex = /```([^\n\r]*)\r?\n([\s\S]*?)```/g;
15039
15073
  let lastIndex = 0;
15040
15074
  let match;
15041
15075
  while ((match = codeBlockRegex.exec(content)) !== null) {
@@ -15043,12 +15077,12 @@ function parseMarkdownWithCodeBlocks(content) {
15043
15077
  if (before.trim()) {
15044
15078
  segments.push({ type: "markdown", content: before });
15045
15079
  }
15046
- const rawLanguage = match[1] ?? "text";
15047
- const runModifier = !!match[2];
15080
+ const tokens = match[1].trim().split(/\s+/).filter(Boolean);
15081
+ let rawLanguage = tokens[0] ?? "text";
15048
15082
  const suffixRunnable = rawLanguage.endsWith("-runnable");
15049
- const runnable = runModifier || suffixRunnable;
15083
+ const runnable = suffixRunnable || tokens.includes("run");
15050
15084
  const baseLanguage = suffixRunnable ? rawLanguage.slice(0, -"-runnable".length) || "text" : rawLanguage;
15051
- segments.push({ type: "code", language: baseLanguage, content: match[3].trim(), runnable });
15085
+ segments.push({ type: "code", language: baseLanguage, content: match[2].trim(), runnable });
15052
15086
  lastIndex = codeBlockRegex.lastIndex;
15053
15087
  }
15054
15088
  const remaining = content.slice(lastIndex);
@@ -15058,7 +15092,7 @@ function parseMarkdownWithCodeBlocks(content) {
15058
15092
  return segments;
15059
15093
  }
15060
15094
  var init_lessonSegmentUtils = __esm({
15061
- "components/core/molecules/lessonSegmentUtils.ts"() {
15095
+ "lib/lessonSegmentUtils.ts"() {
15062
15096
  }
15063
15097
  });
15064
15098
  var BLOOM_CONFIG, BloomQuizBlock;
@@ -14055,6 +14055,19 @@ var init_EmptyState = __esm({
14055
14055
  EmptyState.displayName = "EmptyState";
14056
14056
  }
14057
14057
  });
14058
+ function isLanguageRegistered(lang) {
14059
+ return CODE_LANGUAGE_SET.has(lang) || dynamicallyLoaded.has(lang);
14060
+ }
14061
+ async function loadPrismLanguage(lang) {
14062
+ if (isLanguageRegistered(lang)) return;
14063
+ try {
14064
+ const grammar = codeLanguageLoader ? await codeLanguageLoader(lang) : null;
14065
+ if (grammar) SyntaxHighlighter.registerLanguage(lang, grammar);
14066
+ dynamicallyLoaded.add(lang);
14067
+ } catch {
14068
+ dynamicallyLoaded.add(lang);
14069
+ }
14070
+ }
14058
14071
  function computeFoldRegions(code) {
14059
14072
  const lines = code.split("\n");
14060
14073
  const regions = [];
@@ -14090,7 +14103,8 @@ function computeFoldRegions(code) {
14090
14103
  return regions.sort((a, b) => a.start - b.start);
14091
14104
  }
14092
14105
  function toCodeLanguage(value) {
14093
- return value && CODE_LANGUAGE_SET.has(value) ? value : "text";
14106
+ if (!value) return "text";
14107
+ return value.toLowerCase();
14094
14108
  }
14095
14109
  function generateDiff(oldVal, newVal) {
14096
14110
  const oldLines = oldVal.split("\n");
@@ -14109,7 +14123,24 @@ function generateDiff(oldVal, newVal) {
14109
14123
  }
14110
14124
  return diff;
14111
14125
  }
14112
- var orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log6, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, DIFF_STYLE_FALLBACK, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, CodeBlock;
14126
+ function useLanguageReady(language) {
14127
+ const [ready, setReady] = useState(() => isLanguageRegistered(language));
14128
+ useEffect(() => {
14129
+ if (isLanguageRegistered(language)) {
14130
+ if (!ready) setReady(true);
14131
+ return;
14132
+ }
14133
+ let active = true;
14134
+ loadPrismLanguage(language).then(() => {
14135
+ if (active) setReady(true);
14136
+ });
14137
+ return () => {
14138
+ active = false;
14139
+ };
14140
+ }, [language]);
14141
+ return ready;
14142
+ }
14143
+ var dynamicallyLoaded, codeLanguageLoader, orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log6, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, DIFF_STYLE_FALLBACK, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, CodeBlock;
14113
14144
  var init_CodeBlock = __esm({
14114
14145
  "components/core/molecules/markdown/CodeBlock.tsx"() {
14115
14146
  init_cn();
@@ -14150,6 +14181,8 @@ var init_CodeBlock = __esm({
14150
14181
  SyntaxHighlighter.registerLanguage("graphql", langGraphql);
14151
14182
  SyntaxHighlighter.registerLanguage("orb", orbLanguage);
14152
14183
  SyntaxHighlighter.registerLanguage("lolo", loloLanguage);
14184
+ dynamicallyLoaded = /* @__PURE__ */ new Set();
14185
+ codeLanguageLoader = null;
14153
14186
  orbStyleOverrides = {
14154
14187
  "orb-binding": { color: ORB_COLORS.dark.binding, fontWeight: "bold" },
14155
14188
  "orb-effect": { color: ORB_COLORS.dark.effect, fontWeight: "bold" },
@@ -14265,6 +14298,7 @@ var init_CodeBlock = __esm({
14265
14298
  const isOrb = language === "orb";
14266
14299
  const isLolo = language === "lolo";
14267
14300
  const activeStyle = isOrb ? orbStyle : isLolo ? loloStyle : dark;
14301
+ const languageReady = useLanguageReady(language);
14268
14302
  const eventBus = useEventBus();
14269
14303
  const { t } = useTranslate();
14270
14304
  const scrollRef = useRef(null);
@@ -14388,7 +14422,7 @@ var init_CodeBlock = __esm({
14388
14422
  children: code
14389
14423
  }
14390
14424
  ),
14391
- [code, language, activeStyle]
14425
+ [code, language, activeStyle, languageReady]
14392
14426
  );
14393
14427
  useLayoutEffect(() => {
14394
14428
  const container = codeRef.current;
@@ -14988,10 +15022,10 @@ var init_MarkdownContent = __esm({
14988
15022
  }
14989
15023
  });
14990
15024
 
14991
- // components/core/molecules/lessonSegmentUtils.ts
15025
+ // lib/lessonSegmentUtils.ts
14992
15026
  function parseMarkdownWithCodeBlocks(content) {
14993
15027
  const segments = [];
14994
- const codeBlockRegex = /```([\w-]+)?(?:\s+(run))?\n([\s\S]*?)```/g;
15028
+ const codeBlockRegex = /```([^\n\r]*)\r?\n([\s\S]*?)```/g;
14995
15029
  let lastIndex = 0;
14996
15030
  let match;
14997
15031
  while ((match = codeBlockRegex.exec(content)) !== null) {
@@ -14999,12 +15033,12 @@ function parseMarkdownWithCodeBlocks(content) {
14999
15033
  if (before.trim()) {
15000
15034
  segments.push({ type: "markdown", content: before });
15001
15035
  }
15002
- const rawLanguage = match[1] ?? "text";
15003
- const runModifier = !!match[2];
15036
+ const tokens = match[1].trim().split(/\s+/).filter(Boolean);
15037
+ let rawLanguage = tokens[0] ?? "text";
15004
15038
  const suffixRunnable = rawLanguage.endsWith("-runnable");
15005
- const runnable = runModifier || suffixRunnable;
15039
+ const runnable = suffixRunnable || tokens.includes("run");
15006
15040
  const baseLanguage = suffixRunnable ? rawLanguage.slice(0, -"-runnable".length) || "text" : rawLanguage;
15007
- segments.push({ type: "code", language: baseLanguage, content: match[3].trim(), runnable });
15041
+ segments.push({ type: "code", language: baseLanguage, content: match[2].trim(), runnable });
15008
15042
  lastIndex = codeBlockRegex.lastIndex;
15009
15043
  }
15010
15044
  const remaining = content.slice(lastIndex);
@@ -15014,7 +15048,7 @@ function parseMarkdownWithCodeBlocks(content) {
15014
15048
  return segments;
15015
15049
  }
15016
15050
  var init_lessonSegmentUtils = __esm({
15017
- "components/core/molecules/lessonSegmentUtils.ts"() {
15051
+ "lib/lessonSegmentUtils.ts"() {
15018
15052
  }
15019
15053
  });
15020
15054
  var BLOOM_CONFIG, BloomQuizBlock;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "5.122.10",
3
+ "version": "5.122.12",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [