const fs = require('fs'); const readline = require('readline'); const faq = { groups: [] }; const configRemoveEmptyGroups = true; async function parseFaq() { const fileStream = fs.createReadStream('scripts/faq.md'); const rl = readline.createInterface({ input: fileStream, crlfDelay: Infinity }); let lastGroup = 0; let lastSubgroup = 0; let lastItem = 0; for await (const line of rl) { //console.log(`Line from file: ${line}`); if (line.startsWith('# ')) { const name = line.substring(2); lastSubgroup = 0; faq .groups .push({ name, anchor: slugify(name), subgroups: [] }); lastGroup = faq.groups.length - 1; //console.log('group, index, subgroups: ', faq.groups[lastGroup], lastGroup, lastSubgroup); } else if (line.startsWith('## ')) { const name = line.substring(3); lastItem = 0; faq .groups[lastGroup] .subgroups .push({ name, anchor: slugify(name), items: [] }); lastSubgroup = faq.groups[lastGroup].subgroups.length - 1; //console.log('subgroup, item: ', lastSubgroup, lastItem); } else if (line.startsWith('### ')) { const title = line.substring(4); // new item faq .groups[lastGroup] .subgroups[lastSubgroup] .items .push({ title, content: '' }); lastItem = faq.groups[lastGroup].subgroups[lastSubgroup].items.length - 1; //console.log('subgroup, item: ', lastSubgroup, lastItem); } else if (!line.startsWith('[')) { let newLine = line; if (newLine.length > 0) { // look for markdown URLs const mdRegex = /\[([^\[]+)\]\((.*?)\)/; const mdUrl = line.match(mdRegex); if (mdUrl) { //console.log('mdUrl: ', mdUrl); newLine = newLine.replace(mdUrl[0], ` <Link to={'${mdUrl[2]}'}>${mdUrl[1]}</Link> `); } else { // look for raw URLs const urlRegex = /(https?:\/\/[^ ]*)/; const url = newLine.match(urlRegex); if (url) { newLine = newLine.replace(url[1], ` <Link to={'${url[1]}'}>${url[1]}</Link> `); } } // everything else is text of the last item let item = faq.groups[lastGroup].subgroups[lastSubgroup].items[lastItem]; faq .groups[lastGroup] .subgroups[lastSubgroup] .items[lastItem] .content = item.content + newLine; } } else if (line.indexOf('[not ready]') >= 0) { // everything else is text of the last item let item = faq.groups[lastGroup].subgroups[lastSubgroup].items[lastItem]; item.notReady = true; } } // remove notReady items faq.groups.forEach(g => { g.subgroups.forEach(sg => { sg.items = sg.items.filter(i => i.notReady !== true && i.content.length > 0) }) }) if (configRemoveEmptyGroups) { faq.groups.forEach(g => { g.subgroups = g.subgroups.filter(sb => sb.items.length > 0) }) faq.groups = faq.groups.filter(g => g.subgroups.length > 0) } //console.log(faq.groups[0]); let data = JSON.stringify(faq, null, 2); fs.writeFileSync('src/data/faq-parsed.json', data); } function slugify(value) { return value .normalize('NFD') // split an accented letter in the base letter and the acent .replace(/[\u0300-\u036f]/g, '') // remove all previously split accents .toLowerCase() .trim() .replace(/[^a-z0-9 ]/g, '') // remove all chars not letters, numbers and spaces (to be replaced) .replace(/\s+/g, '-') // separator } parseFaq();