markstream-angular 0.0.9 → 0.1.0-beta.2

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.
@@ -307,6 +307,7 @@ function buildRenderContext(props, events = {}, textStreamState, streamRenderVer
307
307
  customHtmlTags,
308
308
  parseOptions: props.parseOptions,
309
309
  customMarkdownIt: props.customMarkdownIt,
310
+ codeBlockOptions: props.codeBlockOptions,
310
311
  codeBlockProps: props.codeBlockProps,
311
312
  mermaidProps: props.mermaidProps,
312
313
  d2Props: props.d2Props,
@@ -316,7 +317,6 @@ function buildRenderContext(props, events = {}, textStreamState, streamRenderVer
316
317
  themes: props.themes,
317
318
  darkTheme: props.codeBlockDarkTheme,
318
319
  lightTheme: props.codeBlockLightTheme,
319
- monacoOptions: props.codeBlockMonacoOptions,
320
320
  minWidth: props.codeBlockMinWidth,
321
321
  maxWidth: props.codeBlockMaxWidth,
322
322
  },
@@ -584,73 +584,52 @@ function useSafeI18n() {
584
584
  };
585
585
  }
586
586
 
587
- let monacoModule = null;
587
+ let streamDiffsModule = null;
588
588
  let importAttempted$2 = false;
589
589
  let pendingImport$3 = null;
590
- let workersPreloaded = false;
591
- async function preloadWorkers(mod) {
592
- if (workersPreloaded)
593
- return;
594
- workersPreloaded = true;
595
- const existingEnv = globalThis?.MonacoEnvironment;
596
- if (existingEnv && (typeof existingEnv.getWorker === 'function' || typeof existingEnv.getWorkerUrl === 'function'))
597
- return;
598
- if (typeof mod?.preloadMonacoWorkers === 'function')
599
- await mod.preloadMonacoWorkers();
590
+ let runtimePreloaded = false;
591
+ function normalizeStreamDiffsModule(value) {
592
+ const moduleValue = value;
593
+ const source = typeof moduleValue?.createCodeBlockRuntime === 'function' || typeof moduleValue?.useMonaco === 'function'
594
+ ? moduleValue
595
+ : value?.default;
596
+ const factory = source?.createCodeBlockRuntime ?? source?.useMonaco;
597
+ if (typeof factory !== 'function')
598
+ return null;
599
+ return {
600
+ createCodeBlockRuntime: options => factory.call(source, options),
601
+ preloadStreamDiffs: source?.preloadStreamDiffs?.bind(source),
602
+ };
600
603
  }
601
- async function warmupShikiTokenizer(mod) {
602
- const getOrCreateHighlighter = mod?.getOrCreateHighlighter;
603
- if (typeof getOrCreateHighlighter !== 'function')
604
- return true;
605
- try {
606
- const highlighter = await getOrCreateHighlighter(['vitesse-dark', 'vitesse-light'], ['plaintext', 'text', 'javascript']);
607
- if (highlighter && typeof highlighter.codeToTokens === 'function') {
608
- highlighter.codeToTokens('const a = 1', { lang: 'javascript', theme: 'vitesse-dark' });
609
- }
610
- return true;
611
- }
612
- catch (error) {
613
- console.warn('[markstream-angular] Failed to warm up stream-monaco tokenizer; falling back to plain code rendering.', error);
614
- return false;
615
- }
604
+ async function preloadRuntime(mod) {
605
+ if (runtimePreloaded)
606
+ return;
607
+ runtimePreloaded = true;
608
+ if (typeof mod?.preloadStreamDiffs === 'function')
609
+ await mod.preloadStreamDiffs();
616
610
  }
617
- async function getUseMonaco() {
618
- if (monacoModule)
619
- return monacoModule;
611
+ async function getStreamDiffsRuntime() {
612
+ if (streamDiffsModule)
613
+ return streamDiffsModule;
620
614
  if (pendingImport$3)
621
615
  return await pendingImport$3;
622
616
  if (importAttempted$2)
623
617
  return null;
624
618
  pendingImport$3 = (async () => {
625
- // Prefer `stream-diffs`: smaller runtime without the heavy
626
- // `monaco-editor` dependency. `stream-monaco` remains supported as a
627
- // fallback for consumers who install it.
628
- const candidates = [
629
- async () => (await import('stream-diffs')),
630
- async () => (await import('stream-monaco')),
631
- ];
632
- for (const load of candidates) {
633
- try {
634
- const candidate = await load();
635
- const resolved = candidate?.default ?? candidate;
636
- if (typeof resolved?.useMonaco !== 'function')
637
- continue;
638
- monacoModule = resolved;
639
- await preloadWorkers(monacoModule);
640
- const ready = await warmupShikiTokenizer(monacoModule);
641
- if (!ready) {
642
- monacoModule = null;
643
- importAttempted$2 = true;
644
- return null;
645
- }
646
- return monacoModule;
647
- }
648
- catch {
649
- // Try the next candidate runtime.
619
+ try {
620
+ const candidate = normalizeStreamDiffsModule(await import('stream-diffs/markstream'));
621
+ if (!candidate) {
622
+ importAttempted$2 = true;
623
+ return null;
650
624
  }
625
+ streamDiffsModule = candidate;
626
+ await preloadRuntime(streamDiffsModule);
627
+ return streamDiffsModule;
628
+ }
629
+ catch {
630
+ importAttempted$2 = true;
631
+ return null;
651
632
  }
652
- importAttempted$2 = true;
653
- return null;
654
633
  })();
655
634
  try {
656
635
  return await pendingImport$3;
@@ -687,11 +666,13 @@ const LANGUAGE_ALIAS_MAP = {
687
666
  'mjs': 'javascript',
688
667
  'plaintext': 'plain',
689
668
  'py': 'python',
669
+ 'bash': 'shell',
690
670
  'sh': 'shell',
691
671
  'shellscript': 'shell',
692
672
  'text': 'plain',
693
673
  'ts': 'typescript',
694
674
  'tsx': 'tsx',
675
+ 'zsh': 'shell',
695
676
  };
696
677
  const LANGUAGE_LABEL_MAP = {
697
678
  '': 'Text',
@@ -744,16 +725,18 @@ function normalizeLanguageIdentifier(lang) {
744
725
  const token = extractLanguageToken(lang);
745
726
  return LANGUAGE_ALIAS_MAP[token] ?? token;
746
727
  }
747
- function resolveMonacoLanguageId(lang) {
728
+ function resolveLanguageId(lang) {
748
729
  const canonical = normalizeLanguageIdentifier(lang);
749
730
  if (!canonical)
750
731
  return 'plaintext';
751
732
  if (canonical === 'plain')
752
733
  return 'plaintext';
753
- if (canonical === 'jsx')
754
- return 'javascript';
755
- if (canonical === 'tsx')
756
- return 'typescript';
734
+ if (canonical === 'shell')
735
+ return 'zsh';
736
+ if (canonical === 'objectivec')
737
+ return 'objective-c';
738
+ if (canonical === 'objectivecpp')
739
+ return 'objective-cpp';
757
740
  return canonical;
758
741
  }
759
742
  function setLanguageIconResolver(resolver) {
@@ -791,6 +774,7 @@ function getDisplayCode(code, loading) {
791
774
  class PreCodeNodeComponent {
792
775
  constructor() {
793
776
  this.showLineNumbers = false;
777
+ this.whiteSpace = 'pre-wrap';
794
778
  // ─── Line-count caching (mirrors the vue3 PreCodeNode) ─────────────────────
795
779
  this.cachedCode = '';
796
780
  this.cachedCount = 1;
@@ -844,7 +828,7 @@ class PreCodeNodeComponent {
844
828
  if (this.showLineNumbers !== true)
845
829
  return null;
846
830
  const maximumLineNumber = this.codeLineCount;
847
- const width = `${Math.max(4, String(maximumLineNumber).length)}ch`;
831
+ const width = `${Math.max(2, String(maximumLineNumber).length)}ch`;
848
832
  return {
849
833
  '--markstream-pre-line-number-width': width,
850
834
  '--markstream-pre-diff-line-number-width': width,
@@ -852,9 +836,10 @@ class PreCodeNodeComponent {
852
836
  };
853
837
  }
854
838
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.26", ngImport: i0, type: PreCodeNodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
855
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.26", type: PreCodeNodeComponent, isStandalone: true, selector: "markstream-angular-pre-code-node", inputs: { node: "node", showLineNumbers: "showLineNumbers" }, ngImport: i0, template: `<pre
839
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.26", type: PreCodeNodeComponent, isStandalone: true, selector: "markstream-angular-pre-code-node", inputs: { node: "node", showLineNumbers: "showLineNumbers", whiteSpace: "whiteSpace" }, ngImport: i0, template: `<pre
856
840
  [ngClass]="preClasses"
857
841
  [ngStyle]="lineNumberLayoutStyle"
842
+ [style.white-space]="whiteSpace"
858
843
  [attr.aria-busy]="loading"
859
844
  [attr.aria-label]="ariaLabel"
860
845
  [attr.data-language]="language"
@@ -872,6 +857,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.26", ngImpo
872
857
  template: `<pre
873
858
  [ngClass]="preClasses"
874
859
  [ngStyle]="lineNumberLayoutStyle"
860
+ [style.white-space]="whiteSpace"
875
861
  [attr.aria-busy]="loading"
876
862
  [attr.aria-label]="ariaLabel"
877
863
  [attr.data-language]="language"
@@ -886,6 +872,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.26", ngImpo
886
872
  args: [{ required: true }]
887
873
  }], showLineNumbers: [{
888
874
  type: Input
875
+ }], whiteSpace: [{
876
+ type: Input
889
877
  }] } });
890
878
 
891
879
  const isDevEnv = typeof globalThis !== 'undefined' && globalThis.ngDevMode !== false;
@@ -1055,6 +1043,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.26", ngImpo
1055
1043
  const defaultCodeFontFamily = '"SF Mono", Monaco, Consolas, "Ubuntu Mono", "Liberation Mono", "Courier New", monospace';
1056
1044
  const defaultCodeFontSize = 12;
1057
1045
  const defaultCodeLineHeight = 18;
1046
+ const defaultMaxEditorHeight = 500;
1047
+ const defaultTabSize = 4;
1058
1048
  function readPositiveCodeMetric(value) {
1059
1049
  return typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : undefined;
1060
1050
  }
@@ -1100,7 +1090,7 @@ class CodeBlockNodeComponent {
1100
1090
  this.defaultFontSize = defaultCodeFontSize;
1101
1091
  this.fontSize = defaultCodeFontSize;
1102
1092
  this.helpers = null;
1103
- this.runtimeMonacoOptions = null;
1093
+ this.runtimeOptions = null;
1104
1094
  this.createPromise = null;
1105
1095
  this.syncPromise = null;
1106
1096
  this.editorKind = null;
@@ -1110,6 +1100,7 @@ class CodeBlockNodeComponent {
1110
1100
  this.destroyed = false;
1111
1101
  this.copyTimer = null;
1112
1102
  this.deferredHeightSyncRaf = null;
1103
+ this.lastRuntimeHostKey = '';
1113
1104
  this.closeInlinePreview = () => {
1114
1105
  this.inlinePreviewOpen = false;
1115
1106
  this.cdr.markForCheck();
@@ -1145,19 +1136,45 @@ class CodeBlockNodeComponent {
1145
1136
  return this.context?.isDark === true;
1146
1137
  }
1147
1138
  get resolvedDarkTheme() {
1148
- return this.mergedProps.darkTheme ?? this.context?.codeBlockThemes?.darkTheme ?? 'vitesse-dark';
1139
+ const theme = this.mergedProps.theme;
1140
+ if (typeof theme === 'string')
1141
+ return theme;
1142
+ if (theme && typeof theme === 'object' && typeof theme.dark === 'string')
1143
+ return theme.dark;
1144
+ const configured = this.mergedProps.themes ?? this.context?.codeBlockThemes?.themes;
1145
+ return this.mergedProps.darkTheme
1146
+ ?? this.context?.codeBlockThemes?.darkTheme
1147
+ ?? configured?.[0]
1148
+ ?? 'vitesse-dark';
1149
1149
  }
1150
1150
  get resolvedLightTheme() {
1151
- return this.mergedProps.lightTheme ?? this.context?.codeBlockThemes?.lightTheme ?? 'vitesse-light';
1151
+ const theme = this.mergedProps.theme;
1152
+ if (typeof theme === 'string')
1153
+ return theme;
1154
+ if (theme && typeof theme === 'object' && typeof theme.light === 'string')
1155
+ return theme.light;
1156
+ const configured = this.mergedProps.themes ?? this.context?.codeBlockThemes?.themes;
1157
+ return this.mergedProps.lightTheme
1158
+ ?? this.context?.codeBlockThemes?.lightTheme
1159
+ ?? configured?.[1]
1160
+ ?? 'vitesse-light';
1152
1161
  }
1153
1162
  get resolvedThemes() {
1154
- return this.mergedProps.themes ?? this.context?.codeBlockThemes?.themes ?? ['vitesse-dark', 'vitesse-light'];
1163
+ const configured = this.mergedProps.themes ?? this.context?.codeBlockThemes?.themes;
1164
+ if (Array.isArray(configured) && typeof configured[0] === 'string' && typeof configured[1] === 'string')
1165
+ return [configured[0], configured[1]];
1166
+ return [this.resolvedDarkTheme, this.resolvedLightTheme];
1155
1167
  }
1156
- get resolvedMonacoOptions() {
1157
- return {
1158
- ...(this.context?.codeBlockThemes?.monacoOptions || {}),
1159
- ...(this.mergedProps.monacoOptions || {}),
1160
- };
1168
+ get resolvedCodeBlockOptions() {
1169
+ return this.codeBlockOptions ?? this.context?.codeBlockOptions;
1170
+ }
1171
+ get resolvedShowLineNumbers() {
1172
+ if (typeof this.mergedProps.showLineNumbers === 'boolean')
1173
+ return this.mergedProps.showLineNumbers;
1174
+ return this.resolvedCodeBlockOptions?.disableLineNumbers !== true;
1175
+ }
1176
+ get resolvedPreWhiteSpace() {
1177
+ return this.resolvedCodeBlockOptions?.overflow === 'scroll' ? 'pre' : 'pre-wrap';
1161
1178
  }
1162
1179
  get resolvedEnableFontSizeControl() {
1163
1180
  if (typeof this.mergedProps.enableFontSizeControl === 'boolean')
@@ -1198,11 +1215,11 @@ class CodeBlockNodeComponent {
1198
1215
  get canonicalLanguage() {
1199
1216
  return normalizeLanguageIdentifier(this.rawLanguage) || 'plain';
1200
1217
  }
1201
- get monacoLanguage() {
1202
- return resolveMonacoLanguageId(this.rawLanguage);
1218
+ get language() {
1219
+ return resolveLanguageId(this.rawLanguage);
1203
1220
  }
1204
1221
  get isPlainTextLanguage() {
1205
- return this.monacoLanguage === 'plaintext';
1222
+ return this.language === 'plaintext';
1206
1223
  }
1207
1224
  get displayLanguage() {
1208
1225
  const label = languageMap[this.canonicalLanguage] || this.canonicalLanguage;
@@ -1271,28 +1288,26 @@ class CodeBlockNodeComponent {
1271
1288
  return style;
1272
1289
  }
1273
1290
  get preFallbackStyle() {
1274
- const options = this.resolvedMonacoOptions;
1275
1291
  const fontSize = readPositiveCodeMetric(this.fontSize) ?? defaultCodeFontSize;
1276
- const lineHeight = readPositiveCodeMetric(options.lineHeight)
1292
+ const lineHeight = readPositiveCodeMetric(this.resolvedCodeBlockOptions?.lineHeight)
1277
1293
  ?? (fontSize === defaultCodeFontSize ? defaultCodeLineHeight : Math.max(12, Math.round(fontSize * 1.5)));
1278
- const padding = options.padding && typeof options.padding === 'object'
1279
- ? options.padding
1280
- : null;
1281
1294
  const defaultPadding = this.isDiff ? 0 : 8;
1282
- const paddingTop = readPositiveCodeMetric(padding?.top) ?? (padding?.top === 0 ? 0 : defaultPadding);
1283
- const paddingBottom = readPositiveCodeMetric(padding?.bottom) ?? (padding?.bottom === 0 ? 0 : defaultPadding);
1284
- const fontFamily = typeof options.fontFamily === 'string' && options.fontFamily.trim()
1285
- ? options.fontFamily.trim()
1286
- : defaultCodeFontFamily;
1295
+ const padding = this.resolvedCodeBlockOptions?.padding ?? defaultPadding;
1296
+ const fontFamily = this.resolvedCodeBlockOptions?.fontFamily ?? defaultCodeFontFamily;
1287
1297
  return {
1288
1298
  '--markstream-code-font-family': fontFamily,
1289
- '--markstream-code-padding-y': `${paddingTop}px`,
1290
- '--markstream-code-padding-bottom': `${paddingBottom}px`,
1299
+ '--markstream-code-padding-y': `${padding}px`,
1300
+ '--markstream-code-padding-bottom': `${padding}px`,
1291
1301
  '--vscode-editor-font-size': `${fontSize}px`,
1292
1302
  '--vscode-editor-line-height': `${lineHeight}px`,
1293
1303
  'font-family': fontFamily,
1294
1304
  'font-size': `${fontSize}px`,
1295
1305
  'line-height': `${lineHeight}px`,
1306
+ 'padding-top': `${padding}px`,
1307
+ 'padding-bottom': `${padding}px`,
1308
+ 'tab-size': String(this.resolvedCodeBlockOptions?.tabSize ?? defaultTabSize),
1309
+ 'max-height': `${this.resolveMaxHeight()}px`,
1310
+ 'overflow': 'auto',
1296
1311
  };
1297
1312
  }
1298
1313
  ngAfterViewInit() {
@@ -1301,6 +1316,21 @@ class CodeBlockNodeComponent {
1301
1316
  void this.syncEditorState();
1302
1317
  }
1303
1318
  ngOnChanges() {
1319
+ const nextOptions = this.resolvedCodeBlockOptions;
1320
+ const themes = this.resolvedThemes;
1321
+ const runtimeHostKey = [
1322
+ this.resolvedIsDark ? 'dark' : 'light',
1323
+ this.resolvedDarkTheme,
1324
+ this.resolvedLightTheme,
1325
+ themes[0],
1326
+ themes[1],
1327
+ this.resolvedShowLineNumbers ? 'lines' : 'no-lines',
1328
+ ].join('\u0000');
1329
+ if (nextOptions !== this.lastCodeBlockOptions || runtimeHostKey !== this.lastRuntimeHostKey) {
1330
+ this.lastCodeBlockOptions = nextOptions;
1331
+ this.lastRuntimeHostKey = runtimeHostKey;
1332
+ this.disposeRuntimeHelpers();
1333
+ }
1304
1334
  this.applyInitialFontSize();
1305
1335
  if (!this.viewReady)
1306
1336
  return;
@@ -1384,7 +1414,7 @@ class CodeBlockNodeComponent {
1384
1414
  }
1385
1415
  applyInitialFontSize() {
1386
1416
  const previousDefault = this.defaultFontSize;
1387
- const initial = Number(this.resolvedMonacoOptions.fontSize);
1417
+ const initial = readPositiveCodeMetric(this.resolvedCodeBlockOptions?.fontSize) ?? defaultCodeFontSize;
1388
1418
  this.defaultFontSize = Number.isFinite(initial) && initial > 0 ? initial : defaultCodeFontSize;
1389
1419
  if (!(typeof this.fontSize === 'number' && Number.isFinite(this.fontSize) && this.fontSize > 0)
1390
1420
  || this.fontSize === previousDefault
@@ -1413,19 +1443,26 @@ class CodeBlockNodeComponent {
1413
1443
  }
1414
1444
  if (this.syncPromise)
1415
1445
  return this.syncPromise;
1416
- this.syncPromise = (async () => {
1446
+ const activeHelpers = this.helpers;
1447
+ let operationId = this.lifecycleId;
1448
+ const pending = (async () => {
1417
1449
  try {
1418
- const desiredKind = this.isDiff && typeof this.helpers?.createDiffEditor === 'function' ? 'diff' : 'single';
1419
- const desiredStreamMode = this.resolvedLoading !== false;
1450
+ const desiredKind = this.isDiff && typeof activeHelpers.createDiffEditor === 'function' ? 'diff' : 'single';
1451
+ const desiredStreamMode = false;
1420
1452
  if (this.editorKind !== desiredKind
1421
1453
  || this.editorStreamMode !== desiredStreamMode
1422
1454
  || !this.hasRenderedEditorDom(desiredKind)) {
1455
+ operationId += 1;
1423
1456
  await this.recreateEditor(desiredKind, desiredStreamMode);
1424
1457
  }
1425
1458
  else {
1426
1459
  await this.updateEditor();
1427
1460
  }
1428
- await Promise.resolve(this.helpers?.setTheme?.(this.resolvedIsDark ? this.resolvedDarkTheme : this.resolvedLightTheme));
1461
+ if (this.destroyed || this.lifecycleId !== operationId || this.helpers !== activeHelpers)
1462
+ return;
1463
+ await Promise.resolve(activeHelpers.setTheme?.(this.resolvedIsDark ? this.resolvedDarkTheme : this.resolvedLightTheme));
1464
+ if (this.destroyed || this.lifecycleId !== operationId || this.helpers !== activeHelpers)
1465
+ return;
1429
1466
  this.applyEditorFontSize();
1430
1467
  const creationId = this.lifecycleId;
1431
1468
  if (!await this.prepareEditorHandoff(desiredKind, creationId))
@@ -1434,63 +1471,111 @@ class CodeBlockNodeComponent {
1434
1471
  this.scheduleDeferredHeightSync();
1435
1472
  }
1436
1473
  catch {
1437
- this.useFallback = true;
1438
- this.editorReady = false;
1439
- this.cleanupEditor();
1440
- }
1441
- finally {
1442
- this.syncPromise = null;
1443
- this.cdr.markForCheck();
1474
+ if (!this.destroyed && this.lifecycleId === operationId && this.helpers === activeHelpers) {
1475
+ this.useFallback = true;
1476
+ this.editorReady = false;
1477
+ this.cleanupEditor();
1478
+ }
1444
1479
  }
1445
1480
  })();
1446
- return this.syncPromise;
1481
+ const tracked = pending.finally(() => {
1482
+ if (this.syncPromise === tracked)
1483
+ this.syncPromise = null;
1484
+ this.cdr.markForCheck();
1485
+ });
1486
+ this.syncPromise = tracked;
1487
+ return tracked;
1447
1488
  }
1448
1489
  async ensureHelpers() {
1449
1490
  if (this.helpers || this.useFallback)
1450
1491
  return;
1451
1492
  if (this.createPromise)
1452
1493
  return this.createPromise;
1453
- this.createPromise = (async () => {
1454
- const monacoModule = await getUseMonaco();
1455
- if (!monacoModule || typeof monacoModule.useMonaco !== 'function') {
1494
+ const creationId = this.lifecycleId;
1495
+ const pending = (async () => {
1496
+ const runtimeModule = await getStreamDiffsRuntime();
1497
+ if (this.destroyed || this.lifecycleId !== creationId)
1498
+ return;
1499
+ if (!runtimeModule || typeof runtimeModule.createCodeBlockRuntime !== 'function') {
1456
1500
  this.useFallback = true;
1457
1501
  return;
1458
1502
  }
1459
- const configuredUnsafeCSS = typeof this.resolvedMonacoOptions.unsafeCSS === 'string'
1460
- ? this.resolvedMonacoOptions.unsafeCSS
1461
- : '';
1462
- const options = {
1463
- wordWrap: 'on',
1464
- stream: this.resolvedLoading !== false,
1465
- wrappingIndent: 'same',
1466
- readOnly: true,
1467
- minimap: { enabled: false },
1468
- lineNumbers: 'on',
1469
- revealDebounceMs: 75,
1470
- MAX_HEIGHT: 500,
1471
- fontFamily: defaultCodeFontFamily,
1472
- fontSize: this.defaultFontSize,
1473
- lineHeight: defaultCodeLineHeight,
1474
- padding: this.isDiff ? { top: 0, bottom: 0 } : { top: 8, bottom: 8 },
1475
- themes: this.resolvedThemes,
1476
- theme: this.resolvedIsDark ? this.resolvedDarkTheme : this.resolvedLightTheme,
1477
- ...(this.resolvedMonacoOptions || {}),
1478
- // The Angular shell already owns the language/file header. Keep the
1479
- // enhanced surface headerless so it matches the Vue 3 handoff contract.
1480
- disableFileHeader: true,
1481
- unsafeCSS: `[data-file], [data-diff] { --diffs-min-number-column-width-default: 4ch !important; }
1482
- ${configuredUnsafeCSS}`.trim(),
1483
- };
1484
- this.runtimeMonacoOptions = options;
1485
- this.helpers = monacoModule.useMonaco(options);
1503
+ const options = this.buildRuntimeOptions();
1504
+ this.runtimeOptions = options;
1505
+ this.helpers = runtimeModule.createCodeBlockRuntime(options);
1486
1506
  })();
1507
+ const tracked = pending.finally(() => {
1508
+ if (this.createPromise === tracked)
1509
+ this.createPromise = null;
1510
+ });
1511
+ this.createPromise = tracked;
1487
1512
  try {
1488
- await this.createPromise;
1513
+ await tracked;
1489
1514
  }
1490
- finally {
1491
- this.createPromise = null;
1515
+ catch (error) {
1516
+ if (!this.destroyed && this.lifecycleId === creationId)
1517
+ throw error;
1492
1518
  }
1493
1519
  }
1520
+ buildRuntimeOptions() {
1521
+ const userOptions = { ...(this.resolvedCodeBlockOptions ?? {}) };
1522
+ for (const key of [
1523
+ 'maxHeight',
1524
+ 'padding',
1525
+ 'tabSize',
1526
+ 'theme',
1527
+ 'themes',
1528
+ 'themeType',
1529
+ 'language',
1530
+ 'languages',
1531
+ 'stream',
1532
+ 'disableFileHeader',
1533
+ 'onThemeChange',
1534
+ 'renderCustomHeader',
1535
+ 'renderHeaderMetadata',
1536
+ 'renderHeaderPrefix',
1537
+ ])
1538
+ delete userOptions[key];
1539
+ const parseDiffOptions = userOptions.parseDiffOptions && typeof userOptions.parseDiffOptions === 'object'
1540
+ ? userOptions.parseDiffOptions
1541
+ : {};
1542
+ const nativeOptions = this.isDiff
1543
+ ? {
1544
+ diffStyle: 'split',
1545
+ expandUnchanged: false,
1546
+ collapsedContextThreshold: 5,
1547
+ hunkSeparators: 'line-info',
1548
+ ...userOptions,
1549
+ parseDiffOptions: { context: 2, ...parseDiffOptions },
1550
+ }
1551
+ : userOptions;
1552
+ const configuredUnsafeCSS = typeof nativeOptions.unsafeCSS === 'string' ? nativeOptions.unsafeCSS : '';
1553
+ const runtimeFontSize = readPositiveCodeMetric(this.fontSize) ?? defaultCodeFontSize;
1554
+ const runtimeLineHeight = readPositiveCodeMetric(this.resolvedCodeBlockOptions?.lineHeight)
1555
+ ?? (runtimeFontSize === defaultCodeFontSize
1556
+ ? defaultCodeLineHeight
1557
+ : Math.max(12, Math.round(runtimeFontSize * 1.5)));
1558
+ return {
1559
+ overflow: 'wrap',
1560
+ ...nativeOptions,
1561
+ stream: false,
1562
+ MAX_HEIGHT: this.resolvedCodeBlockOptions?.maxHeight ?? defaultMaxEditorHeight,
1563
+ fontFamily: this.resolvedCodeBlockOptions?.fontFamily ?? defaultCodeFontFamily,
1564
+ fontSize: runtimeFontSize,
1565
+ lineHeight: runtimeLineHeight,
1566
+ disableLineNumbers: !this.resolvedShowLineNumbers,
1567
+ themes: [...this.resolvedThemes],
1568
+ theme: this.resolvedIsDark ? this.resolvedDarkTheme : this.resolvedLightTheme,
1569
+ themeType: this.resolvedIsDark ? 'dark' : 'light',
1570
+ disableFileHeader: true,
1571
+ unsafeCSS: `[data-file], [data-diff] { --diffs-min-number-column-width-default: 2ch !important; }
1572
+ ${configuredUnsafeCSS}`.trim(),
1573
+ onThemeChange: () => {
1574
+ this.syncEditorGeometryVars();
1575
+ this.scheduleDeferredHeightSync();
1576
+ },
1577
+ };
1578
+ }
1494
1579
  async recreateEditor(kind, streamMode) {
1495
1580
  const host = this.editorHost?.nativeElement;
1496
1581
  if (!host || !this.helpers)
@@ -1501,19 +1586,19 @@ ${configuredUnsafeCSS}`.trim(),
1501
1586
  host.innerHTML = '';
1502
1587
  this.editorKind = kind;
1503
1588
  this.editorStreamMode = streamMode;
1504
- if (this.runtimeMonacoOptions)
1505
- this.runtimeMonacoOptions.stream = streamMode;
1589
+ if (this.runtimeOptions)
1590
+ this.runtimeOptions.stream = false;
1506
1591
  if (kind === 'diff') {
1507
- await Promise.resolve(this.helpers.createDiffEditor?.(host, this.originalCode, this.resolvedCode, this.monacoLanguage));
1592
+ await Promise.resolve(this.helpers.createDiffEditor?.(host, this.originalCode, this.resolvedCode, this.language));
1508
1593
  this.syncEditorGeometryVars();
1509
1594
  return;
1510
1595
  }
1511
- await Promise.resolve(this.helpers.createEditor?.(host, this.resolvedCode, this.monacoLanguage));
1596
+ await Promise.resolve(this.helpers.createEditor?.(host, this.resolvedCode, this.language));
1512
1597
  this.syncEditorGeometryVars();
1513
1598
  }
1514
- // Align the enhanced surface with the pre-fallback geometry. stream-diffs /
1515
- // pierre honor these CSS variables on the editor host (custom properties
1516
- // inherit across the pierre shadow boundary):
1599
+ // Align the enhanced surface with the pre-fallback geometry. stream-diffs
1600
+ // honors these CSS variables on the editor host (custom properties inherit
1601
+ // across the shadow boundary):
1517
1602
  // - `--diffs-tab-size`: fallback defaults to 4, pierre defaults to 2.
1518
1603
  // - `--diffs-gap-block`: only set when padding is present; the default 8px
1519
1604
  // gap already matches the fallback.
@@ -1521,34 +1606,26 @@ ${configuredUnsafeCSS}`.trim(),
1521
1606
  const host = this.editorHost?.nativeElement;
1522
1607
  if (!host)
1523
1608
  return;
1524
- const tabSize = readPositiveCodeMetric(this.resolvedMonacoOptions.tabSize) ?? 4;
1525
- host.style.setProperty('--diffs-tab-size', String(tabSize));
1526
- const rawPadding = this.resolvedMonacoOptions.padding;
1527
- const hasConfiguredPadding = Boolean(rawPadding && typeof rawPadding === 'object');
1528
- if (hasConfiguredPadding) {
1529
- const top = readPositiveCodeMetric(rawPadding.top) ?? 0;
1530
- host.style.setProperty('--diffs-gap-block', `${top}px`);
1531
- }
1532
- else {
1609
+ host.style.setProperty('--diffs-tab-size', String(this.resolvedCodeBlockOptions?.tabSize ?? defaultTabSize));
1610
+ if (typeof this.resolvedCodeBlockOptions?.padding === 'number')
1611
+ host.style.setProperty('--diffs-gap-block', `${this.resolvedCodeBlockOptions.padding}px`);
1612
+ else
1533
1613
  host.style.removeProperty('--diffs-gap-block');
1534
- }
1535
1614
  }
1536
1615
  async updateEditor() {
1537
1616
  if (!this.helpers)
1538
1617
  return;
1539
1618
  if (this.isDiff && this.editorKind === 'diff' && typeof this.helpers.updateDiff === 'function') {
1540
- await Promise.resolve(this.helpers.updateDiff(this.originalCode, this.resolvedCode, this.monacoLanguage));
1619
+ await Promise.resolve(this.helpers.updateDiff(this.originalCode, this.resolvedCode, this.language));
1541
1620
  return;
1542
1621
  }
1543
- await Promise.resolve(this.helpers.updateCode?.(this.resolvedCode, this.monacoLanguage));
1622
+ await Promise.resolve(this.helpers.updateCode?.(this.resolvedCode, this.language));
1544
1623
  }
1545
- hasRenderedEditorDom(kind) {
1624
+ hasRenderedEditorDom(_kind) {
1546
1625
  const host = this.editorHost?.nativeElement;
1547
1626
  if (!host)
1548
1627
  return false;
1549
- const monacoSelector = kind === 'diff' ? '.monaco-diff-editor' : '.monaco-editor';
1550
1628
  return !!host.querySelector([
1551
- monacoSelector,
1552
1629
  'diffs-container',
1553
1630
  '.stream-diffs-shell',
1554
1631
  '[data-stream-diffs-state]',
@@ -1556,8 +1633,6 @@ ${configuredUnsafeCSS}`.trim(),
1556
1633
  }
1557
1634
  getVisualEditorSurface() {
1558
1635
  return this.editorHost?.nativeElement.querySelector([
1559
- '.monaco-diff-editor',
1560
- '.monaco-editor',
1561
1636
  'diffs-container',
1562
1637
  '[data-stream-diffs-state]',
1563
1638
  '.stream-diffs-shell',
@@ -1607,7 +1682,7 @@ ${configuredUnsafeCSS}`.trim(),
1607
1682
  ? this.helpers?.getDiffEditorView?.()
1608
1683
  : this.helpers?.getEditorView?.();
1609
1684
  try {
1610
- view?.updateOptions?.({ fontSize: this.fontSize, automaticLayout: this.expanded });
1685
+ view?.updateOptions?.({ fontSize: this.fontSize });
1611
1686
  if (this.editorKind === 'diff' && typeof view?.getModifiedEditor === 'function')
1612
1687
  view.getModifiedEditor()?.updateOptions?.({ fontSize: this.fontSize });
1613
1688
  }
@@ -1626,10 +1701,6 @@ ${configuredUnsafeCSS}`.trim(),
1626
1701
  : this.helpers?.getEditorView?.();
1627
1702
  if (!view)
1628
1703
  return;
1629
- try {
1630
- view.updateOptions?.({ automaticLayout: this.expanded });
1631
- }
1632
- catch { }
1633
1704
  const height = this.resolveEditorHeight(view, maxHeight);
1634
1705
  host.style.height = `${height}px`;
1635
1706
  try {
@@ -1671,24 +1742,19 @@ ${configuredUnsafeCSS}`.trim(),
1671
1742
  return Math.max(1, String(this.resolvedCode || '').split('\n').length);
1672
1743
  }
1673
1744
  resolveEditorLineHeight() {
1674
- const fromOptions = Number(this.resolvedMonacoOptions.lineHeight);
1675
- if (Number.isFinite(fromOptions) && fromOptions > 0)
1676
- return fromOptions;
1677
- const fromFontOption = Number(this.resolvedMonacoOptions.fontSize);
1678
- if (Number.isFinite(fromFontOption) && fromFontOption > 0)
1679
- return Math.max(12, Math.round(fromFontOption * 1.35));
1745
+ const configured = readPositiveCodeMetric(this.resolvedCodeBlockOptions?.lineHeight);
1746
+ if (configured)
1747
+ return configured;
1680
1748
  const fromState = Number(this.fontSize);
1681
- if (Number.isFinite(fromState) && fromState > 0)
1682
- return Math.max(12, Math.round(fromState * 1.35));
1683
- return 18;
1749
+ if (Number.isFinite(fromState) && fromState > 0) {
1750
+ return fromState === defaultCodeFontSize
1751
+ ? defaultCodeLineHeight
1752
+ : Math.max(12, Math.round(fromState * 1.5));
1753
+ }
1754
+ return defaultCodeLineHeight;
1684
1755
  }
1685
1756
  resolveMaxHeight() {
1686
- const raw = this.resolvedMonacoOptions.MAX_HEIGHT ?? 500;
1687
- if (typeof raw === 'number' && Number.isFinite(raw))
1688
- return raw > 0 ? raw : 500;
1689
- const matched = String(raw).match(/^(\d+(?:\.\d+)?)/);
1690
- const parsed = matched ? Number.parseFloat(matched[1]) : 500;
1691
- return Number.isFinite(parsed) && parsed > 0 ? parsed : 500;
1757
+ return this.resolvedCodeBlockOptions?.maxHeight ?? defaultMaxEditorHeight;
1692
1758
  }
1693
1759
  cancelDeferredHeightSync() {
1694
1760
  if (this.deferredHeightSyncRaf == null || typeof window === 'undefined')
@@ -1719,6 +1785,16 @@ ${configuredUnsafeCSS}`.trim(),
1719
1785
  catch { }
1720
1786
  this.editorKind = null;
1721
1787
  }
1788
+ disposeRuntimeHelpers() {
1789
+ this.lifecycleId += 1;
1790
+ this.syncPromise = null;
1791
+ this.cleanupEditor();
1792
+ this.helpers = null;
1793
+ this.runtimeOptions = null;
1794
+ this.createPromise = null;
1795
+ this.editorStreamMode = null;
1796
+ this.editorReady = false;
1797
+ }
1722
1798
  resolveCssSize(value) {
1723
1799
  if (value == null || value === '')
1724
1800
  return null;
@@ -1744,14 +1820,14 @@ ${configuredUnsafeCSS}`.trim(),
1744
1820
  }
1745
1821
  }
1746
1822
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.26", ngImport: i0, type: CodeBlockNodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1747
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.26", type: CodeBlockNodeComponent, isStandalone: true, selector: "markstream-angular-code-block-node", inputs: { node: "node", context: "context", props: "props" }, viewQueries: [{ propertyName: "editorHost", first: true, predicate: ["editorHost"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
1823
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.26", type: CodeBlockNodeComponent, isStandalone: true, selector: "markstream-angular-code-block-node", inputs: { node: "node", context: "context", codeBlockOptions: "codeBlockOptions", props: "props" }, viewQueries: [{ propertyName: "editorHost", first: true, predicate: ["editorHost"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
1748
1824
  <div
1749
1825
  class="code-block-container"
1750
1826
  [class.is-dark]="resolvedIsDark"
1751
1827
  [class.is-plain-text]="isPlainTextLanguage"
1752
1828
  [class.is-rendering]="resolvedLoading"
1753
- [attr.data-markstream-monaco]="editorReady && !useFallback ? '1' : null"
1754
- [attr.data-markstream-monaco-diff]="editorReady && isDiff && !useFallback ? '1' : null"
1829
+ [attr.data-markstream-enhanced]="editorReady && !useFallback ? 'true' : 'false'"
1830
+ [attr.data-markstream-enhanced-diff]="editorReady && isDiff && !useFallback ? '1' : null"
1755
1831
  [ngStyle]="containerStyle"
1756
1832
  >
1757
1833
  <div
@@ -1894,7 +1970,8 @@ ${configuredUnsafeCSS}`.trim(),
1894
1970
  class="code-editor-fallback-surface"
1895
1971
  [node]="node"
1896
1972
  [ngStyle]="preFallbackStyle"
1897
- [showLineNumbers]="true"
1973
+ [showLineNumbers]="resolvedShowLineNumbers"
1974
+ [whiteSpace]="resolvedPreWhiteSpace"
1898
1975
  />
1899
1976
 
1900
1977
  <ng-template #editorTpl>
@@ -1909,7 +1986,8 @@ ${configuredUnsafeCSS}`.trim(),
1909
1986
  class="code-editor-fallback-surface"
1910
1987
  [node]="node"
1911
1988
  [ngStyle]="preFallbackStyle"
1912
- [showLineNumbers]="true"
1989
+ [showLineNumbers]="resolvedShowLineNumbers"
1990
+ [whiteSpace]="resolvedPreWhiteSpace"
1913
1991
  />
1914
1992
  </ng-template>
1915
1993
  </ng-container>
@@ -1937,7 +2015,7 @@ ${configuredUnsafeCSS}`.trim(),
1937
2015
  </div>
1938
2016
  </div>
1939
2017
  </ng-template>
1940
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: PreCodeNodeComponent, selector: "markstream-angular-pre-code-node", inputs: ["node", "showLineNumbers"] }, { kind: "component", type: HtmlPreviewFrameComponent, selector: "markstream-angular-html-preview-frame", inputs: ["code", "isDark", "htmlPreviewAllowScripts", "htmlPreviewSandbox", "title", "onClose"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2018
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: PreCodeNodeComponent, selector: "markstream-angular-pre-code-node", inputs: ["node", "showLineNumbers", "whiteSpace"] }, { kind: "component", type: HtmlPreviewFrameComponent, selector: "markstream-angular-html-preview-frame", inputs: ["code", "isDark", "htmlPreviewAllowScripts", "htmlPreviewSandbox", "title", "onClose"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1941
2019
  }
1942
2020
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.26", ngImport: i0, type: CodeBlockNodeComponent, decorators: [{
1943
2021
  type: Component,
@@ -1951,8 +2029,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.26", ngImpo
1951
2029
  [class.is-dark]="resolvedIsDark"
1952
2030
  [class.is-plain-text]="isPlainTextLanguage"
1953
2031
  [class.is-rendering]="resolvedLoading"
1954
- [attr.data-markstream-monaco]="editorReady && !useFallback ? '1' : null"
1955
- [attr.data-markstream-monaco-diff]="editorReady && isDiff && !useFallback ? '1' : null"
2032
+ [attr.data-markstream-enhanced]="editorReady && !useFallback ? 'true' : 'false'"
2033
+ [attr.data-markstream-enhanced-diff]="editorReady && isDiff && !useFallback ? '1' : null"
1956
2034
  [ngStyle]="containerStyle"
1957
2035
  >
1958
2036
  <div
@@ -2095,7 +2173,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.26", ngImpo
2095
2173
  class="code-editor-fallback-surface"
2096
2174
  [node]="node"
2097
2175
  [ngStyle]="preFallbackStyle"
2098
- [showLineNumbers]="true"
2176
+ [showLineNumbers]="resolvedShowLineNumbers"
2177
+ [whiteSpace]="resolvedPreWhiteSpace"
2099
2178
  />
2100
2179
 
2101
2180
  <ng-template #editorTpl>
@@ -2110,7 +2189,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.26", ngImpo
2110
2189
  class="code-editor-fallback-surface"
2111
2190
  [node]="node"
2112
2191
  [ngStyle]="preFallbackStyle"
2113
- [showLineNumbers]="true"
2192
+ [showLineNumbers]="resolvedShowLineNumbers"
2193
+ [whiteSpace]="resolvedPreWhiteSpace"
2114
2194
  />
2115
2195
  </ng-template>
2116
2196
  </ng-container>
@@ -2149,6 +2229,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.26", ngImpo
2149
2229
  args: [{ required: true }]
2150
2230
  }], context: [{
2151
2231
  type: Input
2232
+ }], codeBlockOptions: [{
2233
+ type: Input
2152
2234
  }], props: [{
2153
2235
  type: Input
2154
2236
  }] } });
@@ -2930,6 +3012,7 @@ class DynamicNodeHostComponent {
2930
3012
  for (const [key, value] of Object.entries(this.inputs))
2931
3013
  setValue(key, value);
2932
3014
  }
3015
+ setValue('codeBlockOptions', this.context?.codeBlockOptions);
2933
3016
  componentRef.changeDetectorRef.detectChanges();
2934
3017
  }
2935
3018
  hasDeclaredInput(componentRef, key) {
@@ -8102,6 +8185,19 @@ class NodeOutletComponent {
8102
8185
  get codeMode() {
8103
8186
  return resolveNodeOutletCodeMode(this.node, this.context);
8104
8187
  }
8188
+ get resolvedPreShowLineNumbers() {
8189
+ const explicit = this.context?.codeBlockProps?.showLineNumbers;
8190
+ const disabled = this.context?.codeBlockOptions?.disableLineNumbers;
8191
+ return typeof explicit === 'boolean'
8192
+ ? explicit
8193
+ : typeof disabled === 'boolean'
8194
+ ? !disabled
8195
+ : false;
8196
+ }
8197
+ get resolvedPreWhiteSpace() {
8198
+ const overflow = this.context?.codeBlockOptions?.overflow;
8199
+ return overflow ? (overflow === 'scroll' ? 'pre' : 'pre-wrap') : undefined;
8200
+ }
8105
8201
  get htmlTag() {
8106
8202
  return resolveHtmlTag(this.node);
8107
8203
  }
@@ -8238,18 +8334,23 @@ class NodeOutletComponent {
8238
8334
  <markstream-angular-pre-code-node
8239
8335
  *ngIf="codeMode === 'pre'; else enhancedCode"
8240
8336
  [node]="node"
8241
- [showLineNumbers]="true"
8337
+ [showLineNumbers]="resolvedPreShowLineNumbers"
8338
+ [whiteSpace]="resolvedPreWhiteSpace"
8242
8339
  />
8243
8340
  </ng-template>
8244
8341
  <ng-template #enhancedCode>
8245
- <markstream-angular-code-block-node [node]="node" [context]="context" />
8342
+ <markstream-angular-code-block-node
8343
+ [node]="node"
8344
+ [context]="context"
8345
+ [codeBlockOptions]="context?.codeBlockOptions"
8346
+ />
8246
8347
  </ng-template>
8247
8348
  </ng-container>
8248
8349
 
8249
8350
  <markstream-angular-fallback-node *ngSwitchDefault [node]="fallbackNode" [context]="context" [indexKey]="indexKey" />
8250
8351
  </ng-container>
8251
8352
  </ng-template>
8252
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: i0.forwardRef(() => CommonModule) }, { kind: "directive", type: i0.forwardRef(() => i1.NgIf), selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i0.forwardRef(() => i1.NgSwitch), selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i0.forwardRef(() => i1.NgSwitchCase), selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i0.forwardRef(() => i1.NgSwitchDefault), selector: "[ngSwitchDefault]" }, { kind: "component", type: i0.forwardRef(() => AdmonitionNodeComponent), selector: "markstream-angular-admonition-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => BlockquoteNodeComponent), selector: "markstream-angular-blockquote-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => CheckboxNodeComponent), selector: "markstream-angular-checkbox-node", inputs: ["node"] }, { kind: "component", type: i0.forwardRef(() => CodeBlockNodeComponent), selector: "markstream-angular-code-block-node", inputs: ["node", "context", "props"] }, { kind: "component", type: i0.forwardRef(() => D2BlockNodeComponent), selector: "markstream-angular-d2-block-node", inputs: ["node", "context", "props"] }, { kind: "component", type: i0.forwardRef(() => DefinitionListNodeComponent), selector: "markstream-angular-definition-list-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => DynamicNodeHostComponent), selector: "markstream-angular-dynamic-node-host", inputs: ["component", "node", "context", "indexKey", "inputs"] }, { kind: "component", type: i0.forwardRef(() => EmojiNodeComponent), selector: "markstream-angular-emoji-node", inputs: ["node"] }, { kind: "component", type: i0.forwardRef(() => EmphasisNodeComponent), selector: "markstream-angular-emphasis-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => FallbackComponent), selector: "markstream-angular-fallback-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => FootnoteAnchorNodeComponent), selector: "markstream-angular-footnote-anchor-node", inputs: ["node"] }, { kind: "component", type: i0.forwardRef(() => FootnoteNodeComponent), selector: "markstream-angular-footnote-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => FootnoteReferenceNodeComponent), selector: "markstream-angular-footnote-reference-node", inputs: ["node"] }, { kind: "component", type: i0.forwardRef(() => HardBreakNodeComponent), selector: "markstream-angular-hardbreak-node" }, { kind: "component", type: i0.forwardRef(() => HeadingNodeComponent), selector: "markstream-angular-heading-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => HighlightNodeComponent), selector: "markstream-angular-highlight-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => HtmlBlockNodeComponent), selector: "markstream-angular-html-block-node", inputs: ["node", "context"] }, { kind: "component", type: i0.forwardRef(() => HtmlInlineNodeComponent), selector: "markstream-angular-html-inline-node", inputs: ["node", "context"] }, { kind: "component", type: i0.forwardRef(() => ImageNodeComponent), selector: "markstream-angular-image-node", inputs: ["node"] }, { kind: "component", type: i0.forwardRef(() => InfographicBlockNodeComponent), selector: "markstream-angular-infographic-block-node", inputs: ["node", "context", "props"] }, { kind: "component", type: i0.forwardRef(() => InlineCodeNodeComponent), selector: "markstream-angular-inline-code-node", inputs: ["node", "context", "indexKey", "typewriter", "fade"] }, { kind: "component", type: i0.forwardRef(() => InsertNodeComponent), selector: "markstream-angular-insert-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => LinkNodeComponent), selector: "markstream-angular-link-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => ListItemNodeComponent), selector: "markstream-angular-list-item-node", inputs: ["node", "context", "indexKey", "value"] }, { kind: "component", type: i0.forwardRef(() => ListNodeComponent), selector: "markstream-angular-list-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => MathBlockNodeComponent), selector: "markstream-angular-math-block-node", inputs: ["node"] }, { kind: "component", type: i0.forwardRef(() => MathInlineNodeComponent), selector: "markstream-angular-math-inline-node", inputs: ["node"] }, { kind: "component", type: i0.forwardRef(() => MermaidBlockNodeComponent), selector: "markstream-angular-mermaid-block-node", inputs: ["node", "context", "props"] }, { kind: "component", type: i0.forwardRef(() => ParagraphNodeComponent), selector: "markstream-angular-paragraph-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => PreCodeNodeComponent), selector: "markstream-angular-pre-code-node", inputs: ["node", "showLineNumbers"] }, { kind: "component", type: i0.forwardRef(() => ReferenceNodeComponent), selector: "markstream-angular-reference-node", inputs: ["node"] }, { kind: "component", type: i0.forwardRef(() => StrikethroughNodeComponent), selector: "markstream-angular-strikethrough-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => StrongNodeComponent), selector: "markstream-angular-strong-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => SubscriptNodeComponent), selector: "markstream-angular-subscript-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => SuperscriptNodeComponent), selector: "markstream-angular-superscript-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => TableNodeComponent), selector: "markstream-angular-table-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => TextNodeComponent), selector: "markstream-angular-text-node", inputs: ["node", "context", "indexKey", "typewriter", "fade"] }, { kind: "component", type: i0.forwardRef(() => ThematicBreakNodeComponent), selector: "markstream-angular-thematic-break-node" }, { kind: "component", type: i0.forwardRef(() => VmrContainerNodeComponent), selector: "markstream-angular-vmr-container-node", inputs: ["node", "context", "indexKey"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8353
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: i0.forwardRef(() => CommonModule) }, { kind: "directive", type: i0.forwardRef(() => i1.NgIf), selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i0.forwardRef(() => i1.NgSwitch), selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i0.forwardRef(() => i1.NgSwitchCase), selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i0.forwardRef(() => i1.NgSwitchDefault), selector: "[ngSwitchDefault]" }, { kind: "component", type: i0.forwardRef(() => AdmonitionNodeComponent), selector: "markstream-angular-admonition-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => BlockquoteNodeComponent), selector: "markstream-angular-blockquote-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => CheckboxNodeComponent), selector: "markstream-angular-checkbox-node", inputs: ["node"] }, { kind: "component", type: i0.forwardRef(() => CodeBlockNodeComponent), selector: "markstream-angular-code-block-node", inputs: ["node", "context", "codeBlockOptions", "props"] }, { kind: "component", type: i0.forwardRef(() => D2BlockNodeComponent), selector: "markstream-angular-d2-block-node", inputs: ["node", "context", "props"] }, { kind: "component", type: i0.forwardRef(() => DefinitionListNodeComponent), selector: "markstream-angular-definition-list-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => DynamicNodeHostComponent), selector: "markstream-angular-dynamic-node-host", inputs: ["component", "node", "context", "indexKey", "inputs"] }, { kind: "component", type: i0.forwardRef(() => EmojiNodeComponent), selector: "markstream-angular-emoji-node", inputs: ["node"] }, { kind: "component", type: i0.forwardRef(() => EmphasisNodeComponent), selector: "markstream-angular-emphasis-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => FallbackComponent), selector: "markstream-angular-fallback-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => FootnoteAnchorNodeComponent), selector: "markstream-angular-footnote-anchor-node", inputs: ["node"] }, { kind: "component", type: i0.forwardRef(() => FootnoteNodeComponent), selector: "markstream-angular-footnote-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => FootnoteReferenceNodeComponent), selector: "markstream-angular-footnote-reference-node", inputs: ["node"] }, { kind: "component", type: i0.forwardRef(() => HardBreakNodeComponent), selector: "markstream-angular-hardbreak-node" }, { kind: "component", type: i0.forwardRef(() => HeadingNodeComponent), selector: "markstream-angular-heading-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => HighlightNodeComponent), selector: "markstream-angular-highlight-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => HtmlBlockNodeComponent), selector: "markstream-angular-html-block-node", inputs: ["node", "context"] }, { kind: "component", type: i0.forwardRef(() => HtmlInlineNodeComponent), selector: "markstream-angular-html-inline-node", inputs: ["node", "context"] }, { kind: "component", type: i0.forwardRef(() => ImageNodeComponent), selector: "markstream-angular-image-node", inputs: ["node"] }, { kind: "component", type: i0.forwardRef(() => InfographicBlockNodeComponent), selector: "markstream-angular-infographic-block-node", inputs: ["node", "context", "props"] }, { kind: "component", type: i0.forwardRef(() => InlineCodeNodeComponent), selector: "markstream-angular-inline-code-node", inputs: ["node", "context", "indexKey", "typewriter", "fade"] }, { kind: "component", type: i0.forwardRef(() => InsertNodeComponent), selector: "markstream-angular-insert-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => LinkNodeComponent), selector: "markstream-angular-link-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => ListItemNodeComponent), selector: "markstream-angular-list-item-node", inputs: ["node", "context", "indexKey", "value"] }, { kind: "component", type: i0.forwardRef(() => ListNodeComponent), selector: "markstream-angular-list-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => MathBlockNodeComponent), selector: "markstream-angular-math-block-node", inputs: ["node"] }, { kind: "component", type: i0.forwardRef(() => MathInlineNodeComponent), selector: "markstream-angular-math-inline-node", inputs: ["node"] }, { kind: "component", type: i0.forwardRef(() => MermaidBlockNodeComponent), selector: "markstream-angular-mermaid-block-node", inputs: ["node", "context", "props"] }, { kind: "component", type: i0.forwardRef(() => ParagraphNodeComponent), selector: "markstream-angular-paragraph-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => PreCodeNodeComponent), selector: "markstream-angular-pre-code-node", inputs: ["node", "showLineNumbers", "whiteSpace"] }, { kind: "component", type: i0.forwardRef(() => ReferenceNodeComponent), selector: "markstream-angular-reference-node", inputs: ["node"] }, { kind: "component", type: i0.forwardRef(() => StrikethroughNodeComponent), selector: "markstream-angular-strikethrough-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => StrongNodeComponent), selector: "markstream-angular-strong-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => SubscriptNodeComponent), selector: "markstream-angular-subscript-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => SuperscriptNodeComponent), selector: "markstream-angular-superscript-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => TableNodeComponent), selector: "markstream-angular-table-node", inputs: ["node", "context", "indexKey"] }, { kind: "component", type: i0.forwardRef(() => TextNodeComponent), selector: "markstream-angular-text-node", inputs: ["node", "context", "indexKey", "typewriter", "fade"] }, { kind: "component", type: i0.forwardRef(() => ThematicBreakNodeComponent), selector: "markstream-angular-thematic-break-node" }, { kind: "component", type: i0.forwardRef(() => VmrContainerNodeComponent), selector: "markstream-angular-vmr-container-node", inputs: ["node", "context", "indexKey"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8253
8354
  }
8254
8355
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.26", ngImport: i0, type: NodeOutletComponent, decorators: [{
8255
8356
  type: Component,
@@ -8380,11 +8481,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.26", ngImpo
8380
8481
  <markstream-angular-pre-code-node
8381
8482
  *ngIf="codeMode === 'pre'; else enhancedCode"
8382
8483
  [node]="node"
8383
- [showLineNumbers]="true"
8484
+ [showLineNumbers]="resolvedPreShowLineNumbers"
8485
+ [whiteSpace]="resolvedPreWhiteSpace"
8384
8486
  />
8385
8487
  </ng-template>
8386
8488
  <ng-template #enhancedCode>
8387
- <markstream-angular-code-block-node [node]="node" [context]="context" />
8489
+ <markstream-angular-code-block-node
8490
+ [node]="node"
8491
+ [context]="context"
8492
+ [codeBlockOptions]="context?.codeBlockOptions"
8493
+ />
8388
8494
  </ng-template>
8389
8495
  </ng-container>
8390
8496
 
@@ -8670,7 +8776,7 @@ async function enhanceRenderedHtml(root, options = {}) {
8670
8776
  if (!isActive())
8671
8777
  return handle;
8672
8778
  if (!options.renderCodeBlocksAsPre)
8673
- await renderMonaco(root, cleanupFns, options, isActive);
8779
+ await renderCodeBlocks(root, cleanupFns, options, isActive);
8674
8780
  }
8675
8781
  return handle;
8676
8782
  }
@@ -9061,11 +9167,26 @@ async function renderD2(root, cleanupFns, options, isActive) {
9061
9167
  }
9062
9168
  }
9063
9169
  }
9064
- async function renderMonaco(root, cleanupFns, options, isActive) {
9065
- const monacoModule = await getUseMonaco();
9066
- if (!monacoModule || typeof monacoModule.useMonaco !== 'function' || !isActive())
9067
- return;
9170
+ async function renderCodeBlocks(root, cleanupFns, options, isActive) {
9068
9171
  const preNodes = Array.from(root.querySelectorAll('pre[data-markstream-code-block="1"]'));
9172
+ const fallbackWhiteSpace = options.codeBlockOptions?.overflow === 'scroll' ? 'pre' : 'pre-wrap';
9173
+ const maxHeight = options.codeBlockOptions?.maxHeight;
9174
+ for (const pre of preNodes) {
9175
+ const codeNode = pre.querySelector('code');
9176
+ if (!codeNode)
9177
+ continue;
9178
+ const normalizedLanguage = resolveCodeLanguage(pre, codeNode).trim().toLowerCase();
9179
+ if (normalizedLanguage === 'mermaid' || normalizedLanguage === 'infographic' || normalizedLanguage === 'd2' || normalizedLanguage === 'd2lang')
9180
+ continue;
9181
+ pre.style.whiteSpace = fallbackWhiteSpace;
9182
+ if (typeof maxHeight === 'number') {
9183
+ pre.style.maxHeight = `${maxHeight}px`;
9184
+ pre.style.overflow = 'auto';
9185
+ }
9186
+ }
9187
+ const runtimeModule = await getStreamDiffsRuntime();
9188
+ if (!runtimeModule || typeof runtimeModule.createCodeBlockRuntime !== 'function' || !isActive())
9189
+ return;
9069
9190
  for (const pre of preNodes) {
9070
9191
  if (!isActive())
9071
9192
  return;
@@ -9080,21 +9201,27 @@ async function renderMonaco(root, cleanupFns, options, isActive) {
9080
9201
  const diff = pre.dataset.markstreamDiff === '1';
9081
9202
  const originalCode = decodeDataPayload(pre.dataset.markstreamOriginal);
9082
9203
  const updatedCode = decodeDataPayload(pre.dataset.markstreamUpdated);
9083
- const monacoLanguage = resolveMonacoLanguage(rawLanguage);
9084
- const displayLanguage = rawLanguage.trim() || monacoLanguage;
9204
+ const language = resolveLanguageId(rawLanguage);
9205
+ const displayLanguage = rawLanguage.trim() || language;
9085
9206
  const preStyle = typeof window !== 'undefined' ? window.getComputedStyle(pre) : null;
9086
9207
  const codeStyle = typeof window !== 'undefined' ? window.getComputedStyle(codeNode) : null;
9087
9208
  const measuredPreHeight = pre.getBoundingClientRect().height;
9088
9209
  const fontSize = readCssPixels(codeStyle?.fontSize) ?? 13;
9089
9210
  const lineHeight = readCssPixels(codeStyle?.lineHeight) ?? readCssPixels(preStyle?.lineHeight);
9090
9211
  const paddingTop = readCssPixels(preStyle?.paddingTop);
9091
- const paddingBottom = readCssPixels(preStyle?.paddingBottom);
9092
9212
  const fontFamily = codeStyle?.fontFamily || preStyle?.fontFamily || undefined;
9093
9213
  const shell = createEnhancedBlockShell('code', diff ? `Diff / ${displayLanguage}` : `Code / ${displayLanguage}`, source, false, options, {
9094
9214
  showHeader: options.codeBlockProps?.showHeader !== false,
9095
9215
  });
9096
9216
  shell.body.classList.add('markstream-angular-enhanced-block__body--code');
9097
- shell.body.style.minHeight = `${measuredPreHeight > 0 ? Math.ceil(measuredPreHeight) : estimateCodeBlockHeight(diff ? updatedCode || source : source, diff)}px`;
9217
+ const estimatedHeight = measuredPreHeight > 0
9218
+ ? Math.ceil(measuredPreHeight)
9219
+ : estimateCodeBlockHeight(diff ? updatedCode || source : source, diff);
9220
+ shell.body.style.minHeight = `${typeof maxHeight === 'number' ? Math.min(estimatedHeight, maxHeight) : estimatedHeight}px`;
9221
+ if (typeof maxHeight === 'number') {
9222
+ shell.body.style.maxHeight = `${maxHeight}px`;
9223
+ shell.body.style.overflow = 'auto';
9224
+ }
9098
9225
  if (preStyle) {
9099
9226
  shell.wrapper.style.marginTop = preStyle.marginTop;
9100
9227
  shell.wrapper.style.marginRight = preStyle.marginRight;
@@ -9103,51 +9230,118 @@ async function renderMonaco(root, cleanupFns, options, isActive) {
9103
9230
  }
9104
9231
  const originalPre = pre.cloneNode(true);
9105
9232
  pre.replaceWith(shell.wrapper);
9106
- const configuredUnsafeCSS = typeof options.monacoOptions?.unsafeCSS === 'string'
9107
- ? options.monacoOptions.unsafeCSS
9108
- : '';
9109
- const runtimeUnsafeCSS = `[data-file], [data-diff] { --diffs-min-number-column-width-default: 4ch !important; }
9110
- ${configuredUnsafeCSS}`.trim();
9111
- const helpers = monacoModule.useMonaco({
9112
- themes: ['vitesse-dark', 'vitesse-light'],
9113
- languages: Array.from(new Set([monacoLanguage, 'plaintext'])),
9114
- readOnly: true,
9115
- minimap: { enabled: false },
9116
- lineNumbers: 'on',
9117
- wordWrap: 'off',
9118
- revealDebounceMs: 75,
9119
- MAX_HEIGHT: 500,
9120
- fontSize,
9121
- ...(lineHeight ? { lineHeight } : {}),
9122
- ...(fontFamily ? { fontFamily } : {}),
9123
- ...(paddingTop != null || paddingBottom != null
9124
- ? { padding: { top: paddingTop ?? 0, bottom: paddingBottom ?? 0 } }
9125
- : {}),
9126
- ...(options.monacoOptions || {}),
9127
- // createEnhancedBlockShell already renders the code header. Prevent the
9128
- // enhanced runtime from adding a second `code.<language>` file header.
9233
+ const userOptions = { ...(options.codeBlockOptions ?? {}) };
9234
+ for (const key of [
9235
+ 'maxHeight',
9236
+ 'padding',
9237
+ 'tabSize',
9238
+ 'theme',
9239
+ 'themes',
9240
+ 'themeType',
9241
+ 'language',
9242
+ 'languages',
9243
+ 'stream',
9244
+ 'disableFileHeader',
9245
+ 'onThemeChange',
9246
+ 'renderCustomHeader',
9247
+ 'renderHeaderMetadata',
9248
+ 'renderHeaderPrefix',
9249
+ ])
9250
+ delete userOptions[key];
9251
+ const parseDiffOptions = userOptions.parseDiffOptions && typeof userOptions.parseDiffOptions === 'object'
9252
+ ? userOptions.parseDiffOptions
9253
+ : {};
9254
+ const nativeOptions = diff
9255
+ ? {
9256
+ diffStyle: 'split',
9257
+ expandUnchanged: false,
9258
+ collapsedContextThreshold: 5,
9259
+ hunkSeparators: 'line-info',
9260
+ ...userOptions,
9261
+ parseDiffOptions: { context: 2, ...parseDiffOptions },
9262
+ }
9263
+ : userOptions;
9264
+ const configuredTheme = options.codeBlockProps?.theme;
9265
+ const configuredThemes = options.codeBlockProps?.themes ?? options.themes;
9266
+ const resolvedDarkTheme = typeof configuredTheme === 'string'
9267
+ ? configuredTheme
9268
+ : configuredTheme && typeof configuredTheme === 'object'
9269
+ ? configuredTheme.dark
9270
+ : options.codeBlockProps?.darkTheme ?? options.codeBlockDarkTheme ?? configuredThemes?.[0] ?? 'vitesse-dark';
9271
+ const resolvedLightTheme = typeof configuredTheme === 'string'
9272
+ ? configuredTheme
9273
+ : configuredTheme && typeof configuredTheme === 'object'
9274
+ ? configuredTheme.light
9275
+ : options.codeBlockProps?.lightTheme ?? options.codeBlockLightTheme ?? configuredThemes?.[1] ?? 'vitesse-light';
9276
+ const runtimeThemes = configuredThemes
9277
+ ? [configuredThemes[0], configuredThemes[1]]
9278
+ : [resolvedDarkTheme, resolvedLightTheme];
9279
+ const configuredUnsafeCSS = typeof nativeOptions.unsafeCSS === 'string' ? nativeOptions.unsafeCSS : '';
9280
+ const showLineNumbers = options.codeBlockProps?.showLineNumbers
9281
+ ?? options.codeBlockOptions?.disableLineNumbers !== true;
9282
+ const syncGeometry = () => {
9283
+ shell.body.style.setProperty('--diffs-tab-size', String(options.codeBlockOptions?.tabSize ?? 4));
9284
+ const finalPaddingTop = options.codeBlockOptions?.padding ?? paddingTop;
9285
+ if (finalPaddingTop != null)
9286
+ shell.body.style.setProperty('--diffs-gap-block', `${finalPaddingTop}px`);
9287
+ else
9288
+ shell.body.style.removeProperty('--diffs-gap-block');
9289
+ };
9290
+ syncGeometry();
9291
+ const helpers = runtimeModule.createCodeBlockRuntime({
9292
+ overflow: 'wrap',
9293
+ ...nativeOptions,
9294
+ themes: runtimeThemes,
9295
+ theme: options.isDark ? resolvedDarkTheme : resolvedLightTheme,
9296
+ themeType: options.isDark ? 'dark' : 'light',
9297
+ disableLineNumbers: !showLineNumbers,
9298
+ MAX_HEIGHT: options.codeBlockOptions?.maxHeight ?? 500,
9299
+ fontSize: options.codeBlockOptions?.fontSize ?? fontSize,
9300
+ ...(options.codeBlockOptions?.lineHeight ?? lineHeight ? { lineHeight: options.codeBlockOptions?.lineHeight ?? lineHeight } : {}),
9301
+ ...(options.codeBlockOptions?.fontFamily ?? fontFamily ? { fontFamily: options.codeBlockOptions?.fontFamily ?? fontFamily } : {}),
9302
+ stream: false,
9129
9303
  disableFileHeader: true,
9130
- unsafeCSS: runtimeUnsafeCSS,
9304
+ onThemeChange: syncGeometry,
9305
+ unsafeCSS: `[data-file], [data-diff] { --diffs-min-number-column-width-default: 2ch !important; }
9306
+ ${configuredUnsafeCSS}`.trim(),
9131
9307
  });
9132
9308
  try {
9133
9309
  if (diff && typeof helpers.createDiffEditor === 'function') {
9134
- await helpers.createDiffEditor(shell.body, originalCode, updatedCode || source, monacoLanguage);
9310
+ await helpers.createDiffEditor(shell.body, originalCode, updatedCode || source, language);
9135
9311
  }
9136
9312
  else {
9137
- await helpers.createEditor?.(shell.body, diff ? updatedCode || source : source, monacoLanguage);
9313
+ await helpers.createEditor?.(shell.body, diff ? updatedCode || source : source, language);
9138
9314
  }
9139
- if (!isActive())
9315
+ if (!isActive()) {
9316
+ try {
9317
+ helpers.cleanupEditor?.();
9318
+ }
9319
+ finally {
9320
+ if (shell.wrapper.parentNode)
9321
+ shell.wrapper.replaceWith(originalPre.cloneNode(true));
9322
+ }
9323
+ return;
9324
+ }
9325
+ await helpers.setTheme?.(options.isDark ? resolvedDarkTheme : resolvedLightTheme);
9326
+ if (!isActive()) {
9327
+ try {
9328
+ helpers.cleanupEditor?.();
9329
+ }
9330
+ finally {
9331
+ if (shell.wrapper.parentNode)
9332
+ shell.wrapper.replaceWith(originalPre.cloneNode(true));
9333
+ }
9140
9334
  return;
9141
- await helpers.setTheme?.(options.isDark ? 'vitesse-dark' : 'vitesse-light');
9142
- shell.wrapper.dataset.markstreamMonaco = '1';
9335
+ }
9336
+ shell.wrapper.dataset.markstreamEnhanced = '1';
9143
9337
  if (diff)
9144
- shell.wrapper.dataset.markstreamMonacoDiff = '1';
9338
+ shell.wrapper.dataset.markstreamEnhancedDiff = '1';
9145
9339
  cleanupFns.push(() => {
9146
9340
  try {
9147
9341
  helpers.cleanupEditor?.();
9148
9342
  }
9149
9343
  finally {
9150
- if (shell.wrapper.isConnected)
9344
+ if (shell.wrapper.parentNode)
9151
9345
  shell.wrapper.replaceWith(originalPre.cloneNode(true));
9152
9346
  }
9153
9347
  });
@@ -9184,9 +9378,6 @@ function resolveCodeLanguage(pre, codeNode) {
9184
9378
  const languageClass = Array.from(codeNode.classList).find(className => className.startsWith('language-'));
9185
9379
  return languageClass ? languageClass.slice('language-'.length) : 'plaintext';
9186
9380
  }
9187
- function resolveMonacoLanguage(language) {
9188
- return resolveMonacoLanguageId(language);
9189
- }
9190
9381
  function estimateCodeBlockHeight(source, diff) {
9191
9382
  const lineCount = Math.max(1, source.split('\n').length);
9192
9383
  const perLine = diff ? 20 : 18;
@@ -10090,11 +10281,14 @@ class NodeRendererComponent {
10090
10281
  final: this.effectiveFinal,
10091
10282
  isDark: this.isDark,
10092
10283
  renderCodeBlocksAsPre: this.renderCodeBlocksAsPre,
10093
- monacoOptions: this.codeBlockMonacoOptions,
10094
10284
  d2ThemeId: this.d2Props?.themeId ?? null,
10095
10285
  d2DarkThemeId: this.d2Props?.darkThemeId ?? null,
10096
10286
  showTooltips: this.showTooltips,
10287
+ codeBlockOptions: this.codeBlockOptions,
10097
10288
  codeBlockProps: this.codeBlockProps,
10289
+ codeBlockDarkTheme: this.codeBlockDarkTheme,
10290
+ codeBlockLightTheme: this.codeBlockLightTheme,
10291
+ themes: this.themes,
10098
10292
  mermaidProps: this.mermaidProps,
10099
10293
  d2Props: this.d2Props,
10100
10294
  infographicProps: this.infographicProps,
@@ -10235,7 +10429,7 @@ class NodeRendererComponent {
10235
10429
  }, 3000);
10236
10430
  }
10237
10431
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.26", ngImport: i0, type: NodeRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
10238
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.26", type: NodeRendererComponent, isStandalone: true, selector: "markstream-angular", inputs: { content: "content", nodes: "nodes", final: "final", parseOptions: "parseOptions", customMarkdownIt: "customMarkdownIt", debugPerformance: "debugPerformance", customHtmlTags: "customHtmlTags", htmlPolicy: "htmlPolicy", viewportPriority: "viewportPriority", codeBlockStream: "codeBlockStream", codeBlockDarkTheme: "codeBlockDarkTheme", codeBlockLightTheme: "codeBlockLightTheme", codeBlockMonacoOptions: "codeBlockMonacoOptions", renderCodeBlocksAsPre: "renderCodeBlocksAsPre", codeBlockMinWidth: "codeBlockMinWidth", codeBlockMaxWidth: "codeBlockMaxWidth", codeBlockProps: "codeBlockProps", mermaidProps: "mermaidProps", d2Props: "d2Props", infographicProps: "infographicProps", customComponents: "customComponents", showTooltips: "showTooltips", themes: "themes", isDark: "isDark", customId: "customId", indexKey: "indexKey", typewriter: "typewriter", fade: "fade", batchRendering: "batchRendering", initialRenderBatchSize: "initialRenderBatchSize", renderBatchSize: "renderBatchSize", renderBatchDelay: "renderBatchDelay", renderBatchBudgetMs: "renderBatchBudgetMs", renderBatchIdleTimeoutMs: "renderBatchIdleTimeoutMs", deferNodesUntilVisible: "deferNodesUntilVisible", maxLiveNodes: "maxLiveNodes", liveNodeBuffer: "liveNodeBuffer", allowHtml: "allowHtml", smoothStreaming: "smoothStreaming", smoothStreamingOptions: "smoothStreamingOptions" }, outputs: { copy: "copy", handleArtifactClick: "handleArtifactClick", click: "click", mouseover: "mouseover", mouseout: "mouseout" }, providers: [
10432
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.26", type: NodeRendererComponent, isStandalone: true, selector: "markstream-angular", inputs: { content: "content", nodes: "nodes", final: "final", parseOptions: "parseOptions", customMarkdownIt: "customMarkdownIt", debugPerformance: "debugPerformance", customHtmlTags: "customHtmlTags", htmlPolicy: "htmlPolicy", viewportPriority: "viewportPriority", codeBlockStream: "codeBlockStream", codeBlockDarkTheme: "codeBlockDarkTheme", codeBlockLightTheme: "codeBlockLightTheme", renderCodeBlocksAsPre: "renderCodeBlocksAsPre", codeBlockMinWidth: "codeBlockMinWidth", codeBlockMaxWidth: "codeBlockMaxWidth", codeBlockOptions: "codeBlockOptions", codeBlockProps: "codeBlockProps", mermaidProps: "mermaidProps", d2Props: "d2Props", infographicProps: "infographicProps", customComponents: "customComponents", showTooltips: "showTooltips", themes: "themes", isDark: "isDark", customId: "customId", indexKey: "indexKey", typewriter: "typewriter", fade: "fade", batchRendering: "batchRendering", initialRenderBatchSize: "initialRenderBatchSize", renderBatchSize: "renderBatchSize", renderBatchDelay: "renderBatchDelay", renderBatchBudgetMs: "renderBatchBudgetMs", renderBatchIdleTimeoutMs: "renderBatchIdleTimeoutMs", deferNodesUntilVisible: "deferNodesUntilVisible", maxLiveNodes: "maxLiveNodes", liveNodeBuffer: "liveNodeBuffer", allowHtml: "allowHtml", smoothStreaming: "smoothStreaming", smoothStreamingOptions: "smoothStreamingOptions" }, outputs: { copy: "copy", handleArtifactClick: "handleArtifactClick", click: "click", mouseover: "mouseover", mouseout: "mouseout" }, providers: [
10239
10433
  {
10240
10434
  provide: MARKSTREAM_SMOOTH_STREAMING_SCOPE,
10241
10435
  useExisting: forwardRef(() => NodeRendererComponent),
@@ -10399,14 +10593,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.26", ngImpo
10399
10593
  type: Input
10400
10594
  }], codeBlockLightTheme: [{
10401
10595
  type: Input
10402
- }], codeBlockMonacoOptions: [{
10403
- type: Input
10404
10596
  }], renderCodeBlocksAsPre: [{
10405
10597
  type: Input
10406
10598
  }], codeBlockMinWidth: [{
10407
10599
  type: Input
10408
10600
  }], codeBlockMaxWidth: [{
10409
10601
  type: Input
10602
+ }], codeBlockOptions: [{
10603
+ type: Input
10410
10604
  }], codeBlockProps: [{
10411
10605
  type: Input
10412
10606
  }], mermaidProps: [{
@@ -10897,5 +11091,5 @@ function createMermaidWorkerFromCDN(options) {
10897
11091
  * Generated bundle index. Do not edit.
10898
11092
  */
10899
11093
 
10900
- export { AdmonitionNodeComponent as AdmonitionNode, CodeBlockNodeComponent as AngularCodeBlockNode, BlockquoteNodeComponent as BlockquoteNode, CheckboxNodeComponent as CheckboxNode, CodeBlockNodeComponent as CodeBlockNode, D2BlockNodeComponent as D2BlockNode, DefinitionListNodeComponent as DefinitionListNode, EmojiNodeComponent as EmojiNode, EmphasisNodeComponent as EmphasisNode, FallbackComponent, FootnoteAnchorNodeComponent as FootnoteAnchorNode, FootnoteNodeComponent as FootnoteNode, FootnoteReferenceNodeComponent as FootnoteReferenceNode, HardBreakNodeComponent as HardBreakNode, HeadingNodeComponent as HeadingNode, HighlightNodeComponent as HighlightNode, HtmlBlockNodeComponent as HtmlBlockNode, HtmlInlineNodeComponent as HtmlInlineNode, HtmlPreviewFrameComponent as HtmlPreviewFrame, ImageNodeComponent as ImageNode, InfographicBlockNodeComponent as InfographicBlockNode, InlineCodeNodeComponent as InlineCodeNode, InsertNodeComponent as InsertNode, LinkNodeComponent as LinkNode, ListItemNodeComponent as ListItemNode, ListNodeComponent as ListNode, MARKSTREAM_SMOOTH_STREAMING_SCOPE, MERMAID_DISABLED_CODE, MERMAID_WORKER_BUSY_CODE, CodeBlockNodeComponent as MarkdownCodeBlockNode, NodeRendererComponent as MarkdownRenderComponent, NodeRendererComponent as MarkstreamAngularComponent, MathBlockNodeComponent as MathBlockNode, MathInlineNodeComponent as MathInlineNode, MermaidBlockNodeComponent as MermaidBlockNode, NestedRendererComponent as NestedRenderer, NodeRendererComponent as NodeRenderer, ParagraphNodeComponent as ParagraphNode, PreCodeNodeComponent as PreCodeNode, ReferenceNodeComponent as ReferenceNode, SafeAttrsDirective, SmoothMarkdownStreamService, StrikethroughNodeComponent as StrikethroughNode, StrongNodeComponent as StrongNode, SubscriptNodeComponent as SubscriptNode, SuperscriptNodeComponent as SuperscriptNode, TableNodeComponent as TableNode, TextNodeComponent as TextNode, ThematicBreakNodeComponent as ThematicBreakNode, VmrContainerNodeComponent as VmrContainerNode, WORKER_BUSY_CODE, buildKaTeXCDNWorkerSource, buildMermaidCDNWorkerSource, buildRenderContext, canParseOffthread, clearGlobalCustomComponents, clearKaTeXWorker, clearMermaidWorker, createKaTeXWorkerFromCDN, createMermaidWorkerFromCDN, disableD2, disableKatex, disableMermaid, disposeRenderedHtmlEnhancements, enableD2, enableKatex, enableMermaid, enhanceRenderedHtml, findPrefixOffthread, getCustomComponentsRevision, getCustomNodeComponents, getKaTeXBackpressureDefaults, getKaTeXWorkerLoad, getKatex, getLanguageIcon, getMermaid, getMermaidWorkerLoad, isD2Enabled, isKaTeXWorkerBusy, isKatexEnabled, isMermaidEnabled, languageMap, normalizeLanguageIdentifier, parseNestedMarkdownToNodes, removeCustomComponents, renderKaTeXInWorker, renderKaTeXWithBackpressure, renderMarkdownNodeToHtml, renderMarkdownNodesToHtml, renderMarkdownToHtml, renderNestedMarkdownToHtml, resolveMonacoLanguageId, resolveParsedNodes$1 as resolveParsedNodes, sanitizeHtmlContent, setCustomComponents, setD2Loader, setDefaultI18nMap, setKaTeXBackpressureDefaults, setKaTeXCache, setKaTeXWorker, setKaTeXWorkerDebug, setKaTeXWorkerMaxConcurrency, setKatexLoader, setLanguageIconResolver, setMermaidLoader, setMermaidWorker, setMermaidWorkerClientDebug, setMermaidWorkerMaxConcurrency, subscribeCustomComponents, terminateWorker, useSafeI18n, waitForKaTeXWorkerSlot };
11094
+ export { AdmonitionNodeComponent as AdmonitionNode, CodeBlockNodeComponent as AngularCodeBlockNode, BlockquoteNodeComponent as BlockquoteNode, CheckboxNodeComponent as CheckboxNode, CodeBlockNodeComponent as CodeBlockNode, D2BlockNodeComponent as D2BlockNode, DefinitionListNodeComponent as DefinitionListNode, EmojiNodeComponent as EmojiNode, EmphasisNodeComponent as EmphasisNode, FallbackComponent, FootnoteAnchorNodeComponent as FootnoteAnchorNode, FootnoteNodeComponent as FootnoteNode, FootnoteReferenceNodeComponent as FootnoteReferenceNode, HardBreakNodeComponent as HardBreakNode, HeadingNodeComponent as HeadingNode, HighlightNodeComponent as HighlightNode, HtmlBlockNodeComponent as HtmlBlockNode, HtmlInlineNodeComponent as HtmlInlineNode, HtmlPreviewFrameComponent as HtmlPreviewFrame, ImageNodeComponent as ImageNode, InfographicBlockNodeComponent as InfographicBlockNode, InlineCodeNodeComponent as InlineCodeNode, InsertNodeComponent as InsertNode, LinkNodeComponent as LinkNode, ListItemNodeComponent as ListItemNode, ListNodeComponent as ListNode, MARKSTREAM_SMOOTH_STREAMING_SCOPE, MERMAID_DISABLED_CODE, MERMAID_WORKER_BUSY_CODE, NodeRendererComponent as MarkdownRenderComponent, NodeRendererComponent as MarkstreamAngularComponent, MathBlockNodeComponent as MathBlockNode, MathInlineNodeComponent as MathInlineNode, MermaidBlockNodeComponent as MermaidBlockNode, NestedRendererComponent as NestedRenderer, NodeRendererComponent as NodeRenderer, ParagraphNodeComponent as ParagraphNode, PreCodeNodeComponent as PreCodeNode, ReferenceNodeComponent as ReferenceNode, SafeAttrsDirective, SmoothMarkdownStreamService, StrikethroughNodeComponent as StrikethroughNode, StrongNodeComponent as StrongNode, SubscriptNodeComponent as SubscriptNode, SuperscriptNodeComponent as SuperscriptNode, TableNodeComponent as TableNode, TextNodeComponent as TextNode, ThematicBreakNodeComponent as ThematicBreakNode, VmrContainerNodeComponent as VmrContainerNode, WORKER_BUSY_CODE, buildKaTeXCDNWorkerSource, buildMermaidCDNWorkerSource, buildRenderContext, canParseOffthread, clearGlobalCustomComponents, clearKaTeXWorker, clearMermaidWorker, createKaTeXWorkerFromCDN, createMermaidWorkerFromCDN, disableD2, disableKatex, disableMermaid, disposeRenderedHtmlEnhancements, enableD2, enableKatex, enableMermaid, enhanceRenderedHtml, findPrefixOffthread, getCustomComponentsRevision, getCustomNodeComponents, getKaTeXBackpressureDefaults, getKaTeXWorkerLoad, getKatex, getLanguageIcon, getMermaid, getMermaidWorkerLoad, isD2Enabled, isKaTeXWorkerBusy, isKatexEnabled, isMermaidEnabled, languageMap, normalizeLanguageIdentifier, parseNestedMarkdownToNodes, removeCustomComponents, renderKaTeXInWorker, renderKaTeXWithBackpressure, renderMarkdownNodeToHtml, renderMarkdownNodesToHtml, renderMarkdownToHtml, renderNestedMarkdownToHtml, resolveLanguageId, resolveParsedNodes$1 as resolveParsedNodes, sanitizeHtmlContent, setCustomComponents, setD2Loader, setDefaultI18nMap, setKaTeXBackpressureDefaults, setKaTeXCache, setKaTeXWorker, setKaTeXWorkerDebug, setKaTeXWorkerMaxConcurrency, setKatexLoader, setLanguageIconResolver, setMermaidLoader, setMermaidWorker, setMermaidWorkerClientDebug, setMermaidWorkerMaxConcurrency, subscribeCustomComponents, terminateWorker, useSafeI18n, waitForKaTeXWorkerSlot };
10901
11095
  //# sourceMappingURL=markstream-angular.mjs.map