Markdown preprocessor to compile multiple .md files into one
parent
57c744f288
commit
2f9353df60
|
@ -0,0 +1,145 @@
|
||||||
|
#!/usr/bin/nodejs
|
||||||
|
|
||||||
|
const fsp = require('fs').promises;
|
||||||
|
|
||||||
|
run(process.argv).catch(console.error);
|
||||||
|
|
||||||
|
async function run(argv)
|
||||||
|
{
|
||||||
|
if (argv.length < 3)
|
||||||
|
{
|
||||||
|
console.log('Markdown preprocessor\nUSAGE: ./include.js file.md');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const index_file = await fsp.realpath(argv[2]);
|
||||||
|
const re = /(\{\{[\s\S]*?\}\}|\[[^\]]+\]\([^\)]+\)|(?:^|\n)#[^\n]+)/;
|
||||||
|
let text = await fsp.readFile(index_file, { encoding: 'utf-8' });
|
||||||
|
text = text.split(re);
|
||||||
|
let included = {};
|
||||||
|
let heading = 0, heading_name = '', m;
|
||||||
|
for (let i = 0; i < text.length; i++)
|
||||||
|
{
|
||||||
|
if (text[i].substr(0, 2) == '{{')
|
||||||
|
{
|
||||||
|
// Inclusion
|
||||||
|
let incfile = text[i].substr(2, text[i].length-4);
|
||||||
|
let section = null;
|
||||||
|
let indent = heading;
|
||||||
|
incfile = incfile.replace(/\s*\|\s*indent\s*=\s*(-?\d+)\s*$/, (m, m1) => { indent = parseInt(m1); return ''; });
|
||||||
|
incfile = incfile.replace(/\s*#\s*([^#]+)$/, (m, m1) => { section = m1; return ''; });
|
||||||
|
let inc_heading = section;
|
||||||
|
incfile = rel2abs(index_file, incfile);
|
||||||
|
let inc = await fsp.readFile(incfile, { encoding: 'utf-8' });
|
||||||
|
inc = inc.trim().replace(/^[\s\S]+?\n#/, '#'); // remove until the first header
|
||||||
|
inc = inc.split(re);
|
||||||
|
const indent_str = new Array(indent+1).join('#');
|
||||||
|
let section_start = -1, section_end = -1;
|
||||||
|
for (let j = 0; j < inc.length; j++)
|
||||||
|
{
|
||||||
|
if ((m = /^(\n?)(#+\s*)([\s\S]+)$/.exec(inc[j])))
|
||||||
|
{
|
||||||
|
if (!inc_heading)
|
||||||
|
{
|
||||||
|
inc_heading = m[3].trim();
|
||||||
|
}
|
||||||
|
if (section)
|
||||||
|
{
|
||||||
|
if (m[3].trim() == section)
|
||||||
|
section_start = j;
|
||||||
|
else if (section_start >= 0)
|
||||||
|
{
|
||||||
|
section_end = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inc[j] = m[1] + indent_str + m[2] + m[3];
|
||||||
|
}
|
||||||
|
else if ((m = /^(\[[^\]]+\]\()([^\)]+)(\))$/.exec(inc[j])) && !/^https?:(\/\/)|^#/.exec(m[2]))
|
||||||
|
{
|
||||||
|
const abs_m2 = rel2abs(incfile, m[2]);
|
||||||
|
const rel_m = abs2rel(__filename, abs_m2);
|
||||||
|
if (rel_m.substr(0, 9) == '../../../') // outside docs
|
||||||
|
inc[j] = m[1] + 'https://git.yourcmc.ru/vitalif/vitastor/src/branch/master/'+rel2abs('docs/config/src/include.js', rel_m) + m[3];
|
||||||
|
else
|
||||||
|
inc[j] = m[1] + abs_m2 + m[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (section)
|
||||||
|
{
|
||||||
|
inc = section_start >= 0 ? inc.slice(section_start, section_end < 0 ? inc.length : section_end) : [];
|
||||||
|
}
|
||||||
|
if (inc.length)
|
||||||
|
{
|
||||||
|
if (!inc_heading)
|
||||||
|
inc_heading = heading_name||'';
|
||||||
|
included[incfile+(section ? '#'+section : '')] = '#'+inc_heading.toLowerCase().replace(/\P{L}+/ug, '-').replace(/^-|-$/g, '');
|
||||||
|
inc[0] = inc[0].replace(/^\s+/, '');
|
||||||
|
inc[inc.length-1] = inc[inc.length-1].replace(/\s+$/, '');
|
||||||
|
}
|
||||||
|
text.splice(i, 1, ...inc);
|
||||||
|
i = i + inc.length - 1;
|
||||||
|
}
|
||||||
|
else if ((m = /^\n?(#+)\s*([\s\S]+)$/.exec(text[i])))
|
||||||
|
{
|
||||||
|
// Heading
|
||||||
|
heading = m[1].length;
|
||||||
|
heading_name = m[2].trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let i = 0; i < text.length; i++)
|
||||||
|
{
|
||||||
|
if ((m = /^(\[[^\]]+\]\()([^\)]+)(\))$/.exec(text[i])) && !/^https?:(\/\/)|^#/.exec(m[2]))
|
||||||
|
{
|
||||||
|
const p = m[2].indexOf('#');
|
||||||
|
if (included[m[2]])
|
||||||
|
{
|
||||||
|
text[i] = m[1]+included[m[2]]+m[3];
|
||||||
|
}
|
||||||
|
else if (p >= 0 && included[m[2].substr(0, p)])
|
||||||
|
{
|
||||||
|
text[i] = m[1]+m[2].substr(p)+m[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(text.join(''));
|
||||||
|
}
|
||||||
|
|
||||||
|
function rel2abs(ref, rel)
|
||||||
|
{
|
||||||
|
rel = [ ...ref.replace(/^(.*)\/[^\/]+$/, '$1').split(/\/+/), ...rel.split(/\/+/) ];
|
||||||
|
return killdots(rel).join('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
function abs2rel(ref, abs)
|
||||||
|
{
|
||||||
|
ref = ref.split(/\/+/);
|
||||||
|
abs = abs.split(/\/+/);
|
||||||
|
while (ref.length > 1 && ref[0] == abs[0])
|
||||||
|
{
|
||||||
|
ref.shift();
|
||||||
|
abs.shift();
|
||||||
|
}
|
||||||
|
for (let i = 1; i < ref.length; i++)
|
||||||
|
{
|
||||||
|
abs.unshift('..');
|
||||||
|
}
|
||||||
|
return killdots(abs).join('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
function killdots(rel)
|
||||||
|
{
|
||||||
|
for (let i = 0; i < rel.length; i++)
|
||||||
|
{
|
||||||
|
if (rel[i] == '.')
|
||||||
|
{
|
||||||
|
rel.splice(i, 1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
else if (i >= 1 && rel[i] == '..' && rel[i-1] != '..')
|
||||||
|
{
|
||||||
|
rel.splice(i-1, 2);
|
||||||
|
i -= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rel;
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
# Vitastor
|
||||||
|
|
||||||
|
{{../../../README.md#The Idea}}
|
||||||
|
|
||||||
|
{{../../../README.md#Talks and presentations}}
|
||||||
|
|
||||||
|
{{../../intro/features.en.md}}
|
||||||
|
|
||||||
|
{{../../intro/quickstart.en.md}}
|
||||||
|
|
||||||
|
{{../../intro/architecture.en.md}}
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
{{../../installation/packages.en.md}}
|
||||||
|
|
||||||
|
{{../../installation/proxmox.en.md}}
|
||||||
|
|
||||||
|
{{../../installation/openstack.en.md}}
|
||||||
|
|
||||||
|
{{../../installation/kubernetes.en.md}}
|
||||||
|
|
||||||
|
{{../../installation/source.en.md}}
|
||||||
|
|
||||||
|
{{../../config.en.md|indent=1}}
|
||||||
|
|
||||||
|
{{../../config/common.en.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/network.en.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/layout-cluster.en.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/layout-osd.en.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/osd.en.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/monitor.en.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/pool.en.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/inode.en.md|indent=2}}
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
{{../../usage/cli.en.md}}
|
||||||
|
|
||||||
|
{{../../usage/disk.en.md}}
|
||||||
|
|
||||||
|
{{../../usage/fio.en.md}}
|
||||||
|
|
||||||
|
{{../../usage/nbd.en.md}}
|
||||||
|
|
||||||
|
{{../../usage/qemu.en.md}}
|
||||||
|
|
||||||
|
{{../../usage/nfs.en.md}}
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
{{../../performance/understanding.en.md}}
|
||||||
|
|
||||||
|
{{../../performance/theoretical.en.md}}
|
||||||
|
|
||||||
|
{{../../performance/comparison1.en.md}}
|
||||||
|
|
||||||
|
{{../../intro/author.en.md|indent=1}}
|
|
@ -0,0 +1,65 @@
|
||||||
|
# Vitastor
|
||||||
|
|
||||||
|
{{../../../README-ru.md#Идея|indent=0}}
|
||||||
|
|
||||||
|
{{../../../README-ru.md#Презентации и записи докладов|indent=0}}
|
||||||
|
|
||||||
|
{{../../intro/features.ru.md}}
|
||||||
|
|
||||||
|
{{../../intro/quickstart.ru.md}}
|
||||||
|
|
||||||
|
{{../../intro/architecture.ru.md}}
|
||||||
|
|
||||||
|
## Установка
|
||||||
|
|
||||||
|
{{../../installation/packages.ru.md}}
|
||||||
|
|
||||||
|
{{../../installation/proxmox.ru.md}}
|
||||||
|
|
||||||
|
{{../../installation/openstack.ru.md}}
|
||||||
|
|
||||||
|
{{../../installation/kubernetes.ru.md}}
|
||||||
|
|
||||||
|
{{../../installation/source.ru.md}}
|
||||||
|
|
||||||
|
{{../../config.ru.md|indent=1}}
|
||||||
|
|
||||||
|
{{../../config/common.ru.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/network.ru.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/layout-cluster.ru.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/layout-osd.ru.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/osd.ru.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/monitor.ru.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/pool.ru.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/inode.ru.md|indent=2}}
|
||||||
|
|
||||||
|
## Использование
|
||||||
|
|
||||||
|
{{../../usage/cli.ru.md}}
|
||||||
|
|
||||||
|
{{../../usage/disk.ru.md}}
|
||||||
|
|
||||||
|
{{../../usage/fio.ru.md}}
|
||||||
|
|
||||||
|
{{../../usage/nbd.ru.md}}
|
||||||
|
|
||||||
|
{{../../usage/qemu.ru.md}}
|
||||||
|
|
||||||
|
{{../../usage/nfs.ru.md}}
|
||||||
|
|
||||||
|
## Производительность
|
||||||
|
|
||||||
|
{{../../performance/understanding.ru.md}}
|
||||||
|
|
||||||
|
{{../../performance/theoretical.ru.md}}
|
||||||
|
|
||||||
|
{{../../performance/comparison1.ru.md}}
|
||||||
|
|
||||||
|
{{../../intro/author.ru.md|indent=1}}
|
Loading…
Reference in New Issue