Библиотека Marked в JavaScript предназначена для преобразования Markdown в HTML. Помимо базового синтаксического разбора строк, она предоставляет расширенные возможности работы с потоками данных, что особенно важно при обработке больших документов или интеграции в серверные приложения.
Marked поддерживает потоковую обработку с
использованием интерфейса потоков Node.js (Readable и
Writable). Потоковый парсинг позволяет обрабатывать данные
по мере их поступления, не загружая весь документ в память. Это критично
при работе с большими файлами или динамически поступающими данными,
например, из сетевых источников.
Пример создания потокового парсера:
import { Readable, Writable } from 'stream';
import { marked } from 'marked';
const readable = Readable.from([
'# Заголовок\n',
'Текст абзаца с **жирным выделением**.\n'
]);
const writable = new Writable({
write(chunk, encoding, callback) {
console.log(chunk.toString());
callback();
}
});
readable.on('data', chunk => {
const html = marked.parse(chunk.toString());
writable.write(html);
});
В этом примере Markdown строки поступают из Readable
потока и обрабатываются функцией marked.parse. Результат
сразу передаётся в Writable поток.
Marked позволяет создавать собственные рендереры, что особенно полезно при потоковой обработке, если необходимо модифицировать HTML на лету.
import { marked } from 'marked';
const renderer = {
heading(text, level) {
return `<h${level} class="custom-heading">${text}</h${level}>`;
},
paragraph(text) {
return `<p class="custom-paragraph">${text}</p>`;
}
};
marked.use({ renderer });
const html = marked.parse('# Заголовок\nТекст абзаца');
console.log(html);
Использование собственного рендерера совместимо с потоковой
обработкой, так как marked.parse может вызываться на
фрагментах данных по мере их поступления.
При работе с большими Markdown файлами важно разделять данные на
логические блоки, чтобы избежать перегрузки памяти. Для этого применяют
чтение файла частями с помощью fs.createReadStream и
преобразование каждой части через Marked.
import fs from 'fs';
import { marked } from 'marked';
const stream = fs.createReadStream('large-file.md', { encoding: 'utf-8' });
stream.on('data', chunk => {
const html = marked.parse(chunk);
process.stdout.write(html);
});
stream.on('end', () => {
console.log('\nПарсинг завершён.');
});
Фрагментированный парсинг обеспечивает эффективную обработку и позволяет интегрировать Marked в системы генерации HTML на серверной стороне.
Marked поддерживает асинхронные рендереры, что полезно при работе с динамическими данными, требующими сетевых запросов или операций с базой данных.
import { marked } from 'marked';
const asyncRenderer = {
async code(code, language) {
const highlighted = await someAsyncHighlighter(code, language);
return `<pre><code>${highlighted}</code></pre>`;
}
};
marked.use({ renderer: asyncRenderer });
const html = await marked.parse('# Пример кода\n```js\nconsole.log("Hello");\n```');
console.log(html);
Асинхронный рендерер позволяет безопасно обрабатывать потоки больших документов с вычислительно затратными операциями.
Для более комплексной обработки данных удобно использовать
Transform поток, который принимает Markdown и возвращает
HTML.
import { Transform } from 'stream';
import { marked } from 'marked';
class MarkdownTransform extends Transform {
_transform(chunk, encoding, callback) {
const html = marked.parse(chunk.toString());
this.push(html);
callback();
}
}
const mdStream = new MarkdownTransform();
process.stdin.pipe(mdStream).pipe(process.stdout);
Такой подход позволяет подключать Marked к цепочкам потоков Node.js, включая файлы, сетевые источники и другие потоки данных.
Потоковая обработка позволяет рендерить Markdown на лету в веб-приложениях, например при загрузке больших документов через WebSocket или HTTP Streaming. Потоки позволяют отображать части документа сразу, улучшая отзывчивость интерфейса.
Использование Marked с потоками данных открывает возможности для высокопроизводительной генерации HTML, интеграции с серверными процессами и динамическими источниками Markdown, сохраняя контроль над памятью и производительностью.