UNPKG

leafdoc

Version:

A lightweight NaturalDocs-like LeafletJS-style documentation generator

113 lines (90 loc) 4.68 kB
'use strict'; // Regexp and their explanation: // ^|\n|\r Starts at beginning, or after newline // (?: ) Non-capturing group // \/\/ Two forward slashes // .* Any number of non-newline characters // \s* Any number of whitespace before the slashes... // (?![\n\r]) ...but not a newline. // \s A whitespace/newline at the end // ? But just maybe? // (?![\n\r])\s*\/\/.*\s? Whitespace, slashes, text, maybe a newline // ( )+ One or more comment lines // (?: ) Do not capture individual lines // ( ) Capture the whole set of contiguous lines instead // // (?:^|\n|\r)((?:(?![\n\r])\s*\/\/.*\s?)+) // [\s\S]+ Any character, 1 or more times // ? But lazy, in order to not match ending asterisks // ( ) Capture this // \*+ At least one asterisk at the end... // \/ ...and just one forward slash. // \/ Just one forward slash at the beginning... // \*+ ...and at least one asterisk // (?!\*|\/) Do not match if the next thing is an asterisk or slash // (if not, this will match "/****/ foobar /* */" whole) // (i.e. the first character of [\s\S]+ must be non-asterisk, // non-slash) // (?: ) Do not capture the whole thing // (?:\/\*+(?!\*|\/)([\s\S]+?)\*+\/) // ( multiple single lines )|( block ) // (?:^|\n|\r)((?:(?![\n\r])\s*\/\/.*\s?)+)|(?:\/\*+(?!\*|\/)([\s\S]+?)\*+\/) var commentRegexp = /(?:^|\n|\r)((?:(?![\n\r])\s*\/\/.*\s?)+)|(?:\/\*+(?!\*|\/)([\s\S]+?)\*+\/)/g; // Parser for c-like files/strings // Parses: // - Comment blocks with /* */, ignoring any extra asterisk like /** */ and /*** ***/ // - Single-line comments with //, prepended only by whitespace // - Joins multiple single-line comments as a single block // - The *first* whitespace (or tab) of all single-line comments is ignored function cLikeParser(str) { var match; var parsed = []; while (match = commentRegexp.exec(str)) { var multilineComment = match[1]; var blockComment = match[2]; if (multilineComment) { var cleanMultiline = multilineComment .split('\n') .filter(function (line){ return line !== ''; }) .map(function (line){ return line .replace(/\s*\/\/\s?/, '') // Remove leading double slash, *first* whitespace .replace(/\s*$/, ''); } // Remove trailing whitespace ) .join('\n'); parsed.push(cleanMultiline); } else if (blockComment) { var lines = blockComment.split('\n'); if (lines.length === 1) { // Just trim whitespace around lines[0] = lines[0].trim(); } else { var firstLine = lines[0]; var lastLine = lines[lines.length - 1]; var middleLines = lines.slice(1, lines.length - 1); // Skip the first and last lines // Remove as much leading whitespace as the last line and then an asterisk, // if every line in the middle of block has that much whitespace and then an asterisk if (lastLine.trim() === '') { var lastLineRegexp = new RegExp('^' + lastLine + '\\*'); if (middleLines.every(function (line){ return line.match(lastLineRegexp) || line === ''; })) { middleLines = middleLines.map(function (line){ return line.replace(/^\s*\*/, ''); }); // Remove one leading whitespace, if every line in the middle block has it // (or the line is empty) if (middleLines.every(function (line){ return line.match(/^\s/) || line === ''; })) { middleLines = middleLines.map(function (line){ return line.replace(/^\s/, ''); }); firstLine = firstLine.replace(/^\s/, ''); } } } lines = ([firstLine]).concat(middleLines, [lastLine]); // console.log(JSON.stringify(blockComment), ",", JSON.stringify(lastLine), '→', lines.map(JSON.stringify)); } var cleanBlock = lines .map(function (line){ return line.replace(/\s*$/, ''); }) // Remove trailing whitespace .join('\n'); parsed.push(cleanBlock); } } console.log(parsed); return parsed; } module.exports = cLikeParser;