Генератор документации на Node.js
от aNNiMON
В какой-то момент, при создании очередного модуля к OwnLang, возникла сложность в поддержании документации. Сначала она писалась вручную в Markdown и выглядела подобным образом:
Мне же нужно было вести список модулей на русском и английском языке, сохранять в HTML в двух вариантах (все модули и модули только для Android), в Markdown в один файл и в несколько файлов для GitBook (на каждый модуль один файл, причём язык подсветки нужно было менять с own на scala).
Вырисовывалась такая структура
Поочерёдно загрузив каждый модуль, можно программно получить список все модулей и его функций, после чего сгенерировать файл с приведённой структурой.
Так как описания и примеры нужно заполнять вручную, вариант сохранять в JSON не подходит - экранировать символы и заменять переносы строк на \n не очень удобно. Поэтому был взят формат YAML.
Из такого представления можно легко сконвертировать описания в Markdown:
Для этого нужен парсер markdown, парсер yaml и библиотека для подсветки синтаксиса (для подсветки кода в html). Всё это, а также многое другое, уже реализовано для Node.js, на котором и напишем генератор.
Так как Node.js нужен лишь для простой задачи, то устанавливать его и качать редакторы будет излишним, можно обойтись облачными платформами, например Cloud 9
При создании нового проекта, выбираем Node.js и получаем настроенный проект с онлайн-редактором. Можно сразу же писать код.
Первым делом устанавливаем необходимые модули:
npm install marked - парсер Markdown
npm install yamljs - парсер Yaml
npm install highlight.js - известная библиотека для подсветки синтаксиса
npm install underscore - underscore.js незаменимая вещь для коллекций
npm install string-template - шаблонизатор, чтоб не конкатенировать строки
После этого можно приступать к разработке.
Парсим YAML
Теперь в modules у нас полная иерархия описания модулей. Пройдёмся по массиву и сгенерируем md для двух языков.
underscore.each перебирает все элементы массива, аналог for-in, только в функциональном стиле.
fs.createWriteStream создаёт файл для записи.
Далее записываем в файл нужные данные при помощи шаблонизатора.
Теперь у нас генерируется полноценный текстовый файл, мы вольны фильтровать модули, сортировать функции, чтобы на выходе получить желаемый результат.
Теперь сгенерируем html из Markdown-файла.
Можно реализовать свою подсветку синтаксиса в highlight.js на основе уже существующих языков. Они находятся тут /node_modules/highlight.js/lib/languages.
Вот и всё, генератор документации готов. Можно добавить побольше настроек, возможность запуска из командной строки, подключение хедера и футера к каждому файлу, что и было сделано в конечном результате.
Файлы проекта: docbuilder.zip
- ## Модуль-types
- Содержит функции для проверки и преобразования типов.
- ### Функции
- `typeof(value)` - возвращает тип переданного в функцию значения.
- ```own
- print typeof(1) // 1 (NUMBER)
- print typeof("text") // 2 (STRING)
- print typeof([]) // 3 (ARRAY)
- ```
- `string(value)` - преобразует значение в строку.
- ```own
- print typeof(string(1)) // 2 (STRING)
- ```
Мне же нужно было вести список модулей на русском и английском языке, сохранять в HTML в двух вариантах (все модули и модули только для Android), в Markdown в один файл и в несколько файлов для GitBook (на каждый модуль один файл, причём язык подсветки нужно было менять с own на scala).
Вырисовывалась такая структура
- Модули:
- - Модуль 1
- - название
- - поддержка (все платформы / ПК / Android)
- - описание
- - описание на русском
- - функции
- - функция 1
- - название
- - список аргументов
- - описание
- - описание на русском
- - пример
- - константы
- - типы данных
- - Модуль 2
Поочерёдно загрузив каждый модуль, можно программно получить список все модулей и его функций, после чего сгенерировать файл с приведённой структурой.
Так как описания и примеры нужно заполнять вручную, вариант сохранять в JSON не подходит - экранировать символы и заменять переносы строк на \n не очень удобно. Поэтому был взят формат YAML.
- ---
- -
- name: "types"
- scope: "both"
- desc: "Contains functions for type checking and conversion"
- desc_ru: "Содержит функции для проверки и преобразования типов"
- functions:
- -
- name: "string"
- args: "value"
- desc: "converts value to string"
- desc_ru: "преобразует значение в строку"
- example: |-
- print typeof(string(1)) // 2 (STRING)
- -
- name: "typeof"
- args: "value"
- desc: "returns the type of value"
- desc_ru: "возвращает тип переданного значения"
- example: |-
- print typeof(1) // 1 (NUMBER)
- print typeof("text") // 2 (STRING)
- print typeof([]) // 3 (ARRAY)
Для сравнения, вот так пришлось бы писать в случае с JSON.
Из такого представления можно легко сконвертировать описания в Markdown:
- {name}({args}) - {desc}
- ```own
- {example}
- ```
Для этого нужен парсер markdown, парсер yaml и библиотека для подсветки синтаксиса (для подсветки кода в html). Всё это, а также многое другое, уже реализовано для Node.js, на котором и напишем генератор.
Так как Node.js нужен лишь для простой задачи, то устанавливать его и качать редакторы будет излишним, можно обойтись облачными платформами, например Cloud 9
При создании нового проекта, выбираем Node.js и получаем настроенный проект с онлайн-редактором. Можно сразу же писать код.
Первым делом устанавливаем необходимые модули:
npm install marked - парсер Markdown
npm install yamljs - парсер Yaml
npm install highlight.js - известная библиотека для подсветки синтаксиса
npm install underscore - underscore.js незаменимая вещь для коллекций
npm install string-template - шаблонизатор, чтоб не конкатенировать строки
После этого можно приступать к разработке.
Парсим YAML
- const yaml = require('yamljs');
- let modules = yaml.load('modules.yml');
Теперь в modules у нас полная иерархия описания модулей. Пройдёмся по массиву и сгенерируем md для двух языков.
- const fs = require('fs'),
- underscore = require('underscore');
- const langs = ["en", "ru"];
- underscore.each(langs, function(lang) {
- const path = "/modules_" + lang;
- const file = fs.createWriteStream(path + '.md');
- underscore.each(modules, function(module) {
- file.write('\n\n');
- processMarkdownModule(file, lang, module);
- file.write('\n');
- });
- file.end();
- console.log(path + '.md generated.');
- });
fs.createWriteStream создаёт файл для записи.
Далее записываем в файл нужные данные при помощи шаблонизатора.
- file.write(format('## {name} {#{anchorname}}\n\n', {
- name: module.name,
- anchorname: module.name
- }));
- file.write(format('{desc}\n', {desc: getValue(module, 'desc', lang)}));
Теперь у нас генерируется полноценный текстовый файл, мы вольны фильтровать модули, сортировать функции, чтобы на выходе получить желаемый результат.
Теперь сгенерируем html из Markdown-файла.
- const hljs = require('highlight.js');
- const marked = require('marked');
- marked.setOptions({
- highlight: code => hljs.highlight('own', code).value
- });
- underscore.each(langs, function(lang) {
- const path = "/modules_" + lang;
- fs.readFile(path + '.md', 'utf8', function (err, data) {
- if (err) return console.log(err);
- const file = fs.createWriteStream(path + '.html');
- file.write(marked(data, {renderer: markedRenderer}));
- file.end();
- console.log(path + '.html generated.');
- });
- });
Можно реализовать свою подсветку синтаксиса в highlight.js на основе уже существующих языков. Они находятся тут /node_modules/highlight.js/lib/languages.
Вот и всё, генератор документации готов. Можно добавить побольше настроек, возможность запуска из командной строки, подключение хедера и футера к каждому файлу, что и было сделано в конечном результате.
Полный исходник (245 строк)
Файлы проекта: docbuilder.zip