function preprocess(sourceText, filename) {
	const text = sourceText.startsWith(BOM) ? sourceText.slice(1) : sourceText;
	const ast = fromMarkdown(text);
	const blocks = [];

	blocksCache.set(filename, blocks);

	/**
	 * During the depth-first traversal, keep track of any sequences of HTML
	 * comment nodes containing `eslint-*` or `global` comments. If a code
	 * block immediately follows such a sequence, insert the comments at the
	 * top of the code block. Any non-ESLint comment or other node type breaks
	 * and empties the sequence.
	 * @type {string[]}
	 */
	let htmlComments = [];

	traverse(ast, {
		"*"() {
			htmlComments = [];
		},

		/**
		 * Visit a code node.
		 * @param {CodeNode} node The visited node.
		 * @returns {void}
		 */
		code(node) {
			if (node.lang) {
				const comments = [];

				for (const comment of htmlComments) {
					if (comment.trim() === "eslint-skip") {
						htmlComments = [];
						return;
					}

					comments.push(`/*${comment}*/`);
				}

				htmlComments = [];

				blocks.push({
					...node,
					baseIndentText: getIndentText(text, node),
					comments,
					rangeMap: getBlockRangeMap(text, node, comments),
				});
			}
		},

		/**
		 * Visit an HTML node.
		 * @param {HtmlNode} node The visited node.
		 * @returns {void}
		 */
		html(node) {
			const comment = getComment(node.value);

			if (comment) {
				htmlComments.push(comment);
			} else {
				htmlComments = [];
			}
		},
	});

	return blocks.map((block, index) => {
		const [language] = block.lang.trim().split(" ");
		const fileExtension = Object.hasOwn(languageToFileExtension, language)
			? languageToFileExtension[language]
			: language;

		return {
			filename: fileNameFromMeta(block) ?? `${index}.${fileExtension}`,
			text: [...block.comments, block.value, ""].join("\n"),
		};
	});
}
Extracts lintable code blocks from Markdown text.
@param {string} sourceText The text of the file.
@param {string} filename The filename of the file
@returns {Array<{ filename: string, text: string }>} Source code blocks to lint.