private static void ProcessCodeBlock()

in src/Elastic.Markdown/Myst/CodeBlocks/EnhancedCodeBlockParser.cs [141:255]


	private static void ProcessCodeBlock(
		StringLineGroup lines,
		string language,
		EnhancedCodeBlock codeBlock,
		ParserContext context)
	{
		string argsString;
		if (codeBlock.Arguments == null)
			argsString = "";
		else if (codeBlock.Info?.IndexOf('{') == -1)
			argsString = codeBlock.Arguments ?? "";
		else
		{
			// if the code block starts with {code-block} and is followed by a language, we need to skip the language
			var parts = codeBlock.Arguments.Split();
			argsString = parts.Length > 1 && CodeBlock.Languages.Contains(parts[0])
				? string.Join(" ", parts[1..])
				: codeBlock.Arguments;
		}

		var codeBlockArgs = CodeBlockArguments.Default;
		if (!CodeBlockArguments.TryParse(argsString, out var codeArgs))
			codeBlock.EmitError($"Unable to parse code block arguments: {argsString}. Valid arguments are {CodeBlockArguments.KnownKeysString}.");
		else
			codeBlockArgs = codeArgs;

		var callOutIndex = 0;
		var originatingLine = 0;
		for (var index = 0; index < lines.Lines.Length; index++)
		{
			originatingLine++;
			var line = lines.Lines[index];
			if (index == 0 && language == "console")
			{
				codeBlock.ApiCallHeader = line.ToString();
				var s = new StringSlice("");
				lines.Lines[index] = new StringLine(ref s);
				continue;
			}

			var span = line.Slice.AsSpan();
			if (codeBlockArgs.UseSubstitutions)
			{
				if (span.ReplaceSubstitutions(context.YamlFrontMatter?.Properties, context.Build.Collector, out var frontMatterReplacement))
				{
					var s = new StringSlice(frontMatterReplacement);
					lines.Lines[index] = new StringLine(ref s);
					span = lines.Lines[index].Slice.AsSpan();
				}

				if (span.ReplaceSubstitutions(context.Substitutions, context.Build.Collector, out var globalReplacement))
				{
					var s = new StringSlice(globalReplacement);
					lines.Lines[index] = new StringLine(ref s);
					span = lines.Lines[index].Slice.AsSpan();
				}
			}

			if (codeBlock.OpeningFencedCharCount > 3)
				continue;

			if (codeBlockArgs.UseCallouts)
			{
				List<CallOut> callOuts = [];
				var hasClassicCallout = span.IndexOf("<") > 0 && span.LastIndexOf(">") == span.Length - 1;
				if (hasClassicCallout)
				{
					var matchClassicCallout = CallOutParser.CallOutNumber().EnumerateMatches(span);
					callOuts.AddRange(
						EnumerateAnnotations(matchClassicCallout, ref span, ref callOutIndex, originatingLine, false)
					);
				}

				// only support magic callouts for smaller line lengths
				if (callOuts.Count == 0 && span.Length < 200)
				{
					var matchInline = CallOutParser.MathInlineAnnotation().EnumerateMatches(span);
					callOuts.AddRange(
						EnumerateAnnotations(matchInline, ref span, ref callOutIndex, originatingLine, true)
					);
				}

				codeBlock.CallOuts.AddRange(callOuts);
			}
		}

		//update string slices to ignore call outs
		if (codeBlock.CallOuts.Count > 0)
		{
			var callouts = codeBlock.CallOuts.Aggregate(new Dictionary<int, CallOut>(), (acc, curr) =>
			{
				if (acc.TryAdd(curr.Line, curr))
					return acc;
				if (acc[curr.Line].SliceStart > curr.SliceStart)
					acc[curr.Line] = curr;
				return acc;
			});

			foreach (var callout in callouts.Values)
			{
				var line = lines.Lines[callout.Line - 1];
				var newSpan = line.Slice.AsSpan()[..callout.SliceStart];
				var s = new StringSlice(newSpan.ToString());
				lines.Lines[callout.Line - 1] = new StringLine(ref s);
			}
		}

		var inlineAnnotations = codeBlock.CallOuts.Count(c => c.InlineCodeAnnotation);
		var classicAnnotations = codeBlock.CallOuts.Count - inlineAnnotations;
		if (inlineAnnotations > 0 && classicAnnotations > 0)
			codeBlock.EmitError("Both inline and classic callouts are not supported");

		if (inlineAnnotations > 0)
			codeBlock.InlineAnnotations = true;
	}