support for multiple regions with the same name
This commit is contained in:
parent
c64c3d045e
commit
593938011f
|
@ -7,13 +7,13 @@ var taskListing = require('gulp-task-listing');
|
|||
var docShredder = require('../doc-shredder');
|
||||
|
||||
var shredOptions = {
|
||||
examplesDir: "test_source",
|
||||
examplesDir: "test_source/foo",
|
||||
fragmentsDir: "test_fragments"
|
||||
};
|
||||
|
||||
gulp.task('help', taskListing);
|
||||
|
||||
gulp.task('shred', function() {
|
||||
gulp.task('shred', ['clean'], function() {
|
||||
return docShredder.shred(shredOptions);
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
// #docregion import,twoparts
|
||||
import {Component, View, bootstrap} from 'angular2/angular2';
|
||||
// #enddocregion twoparts, import
|
||||
|
||||
@Component({
|
||||
selector: 'my-app'
|
||||
})
|
||||
@View({
|
||||
template: '<h1 id="output">My first Angular 2 App</h1>'
|
||||
})
|
||||
class AppComponent {
|
||||
}
|
||||
|
||||
// #docregion bootstrap, twoparts
|
||||
bootstrap(AppComponent);
|
||||
// #enddocregion twoparts
|
||||
// to be included in bootstrap...
|
||||
// #enddocregion
|
|
@ -1,3 +1,5 @@
|
|||
var _ = require('lodash');
|
||||
|
||||
module.exports = function regionExtractor() {
|
||||
|
||||
var nullLine = '###';
|
||||
|
@ -10,37 +12,82 @@ module.exports = function regionExtractor() {
|
|||
// or // #docregion foo for js/ts
|
||||
// 2) In back: a comment marker followed by '#enddocregion'
|
||||
// Regions can be nested and any regions not 'closed' are automatically closed at the end of the doc.
|
||||
|
||||
// empty enddocregion always closes last region started.
|
||||
// enddocregions with names that do no match start region tags get ignored.
|
||||
|
||||
return function(content, commentPrefixes) {
|
||||
|
||||
var lines = result = content.split(/\r?\n/);
|
||||
var docs = [];
|
||||
var docStack = [];
|
||||
var doc = null;
|
||||
|
||||
var docStack = [];
|
||||
var docMap = {};
|
||||
var doc;
|
||||
var regionNames;
|
||||
lines.forEach(function(line, ix) {
|
||||
if (isCommentLine(line, commentPrefixes)) {
|
||||
if (hasRegionTag(line)) {
|
||||
if (doc) docStack.push(doc);
|
||||
doc = {startIx: ix, regionName: getRegionName(line)};
|
||||
lines[ix] = nullLine;
|
||||
docs.push(doc);
|
||||
|
||||
regionNames = getRegionNames(line);
|
||||
regionNames.forEach(function(rn) {
|
||||
doc = docMap[rn];
|
||||
if (!doc) {
|
||||
// regionName may be ''
|
||||
doc = {regionName: rn, ranges: [ { startIx: ix} ] };
|
||||
docMap[rn] = doc;
|
||||
} else {
|
||||
// only add a new range if prev range is closed
|
||||
var lastRange = doc.ranges[doc.ranges.length-1];
|
||||
if (lastRange.endIx) {
|
||||
doc.ranges.push({startIx: ix});
|
||||
}
|
||||
}
|
||||
docStack.push(doc);
|
||||
});
|
||||
|
||||
} else if (hasEndRegionTag(line)) {
|
||||
if (doc) {
|
||||
lines[ix] = nullLine;
|
||||
doc.endIx = ix;
|
||||
doc = docStack.pop();
|
||||
}
|
||||
lines[ix] = nullLine;
|
||||
regionNames = getEndRegionNames(line);
|
||||
regionNames.forEach(function(rn) {
|
||||
// handle endregions with no name specially.
|
||||
// They operate on the last region created.
|
||||
if (rn.length == 0) {
|
||||
if (docStack.length) {
|
||||
// update last item on the stack
|
||||
doc = docStack.pop();
|
||||
doc.ranges[doc.ranges.length - 1].endIx = ix;
|
||||
}
|
||||
} else {
|
||||
doc = docMap[rn];
|
||||
// ignore endregion if name is specified but not found.
|
||||
if (doc) {
|
||||
doc.ranges[doc.ranges.length - 1].endIx = ix;
|
||||
// remove doc from stack
|
||||
_.remove(docStack, function (item) {
|
||||
return item.regionName === rn;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var docs = _.values(docMap);
|
||||
docs.forEach(function(doc) {
|
||||
var fragLines, content;
|
||||
if (doc.endIx) {
|
||||
fragLines = lines.slice(doc.startIx + 1, doc.endIx);
|
||||
} else {
|
||||
fragLines = lines.slice(doc.startIx + 1);
|
||||
}
|
||||
var content;
|
||||
var fragLines = [];
|
||||
doc.ranges.forEach(function (range) {
|
||||
var subLines;
|
||||
if (range.endIx) {
|
||||
subLines = lines.slice(range.startIx + 1, range.endIx);
|
||||
} else {
|
||||
subLines = lines.slice(range.startIx + 1);
|
||||
}
|
||||
fragLines = fragLines.concat(subLines);
|
||||
});
|
||||
fragLines = trimLeftIndent(fragLines);
|
||||
content = fragLines.join('\n');
|
||||
// eliminate all #docregion lines
|
||||
|
@ -94,13 +141,23 @@ function hasEndRegionTag(line) {
|
|||
return line.indexOf("#enddocregion") >= 0;
|
||||
}
|
||||
|
||||
function getRegionName(line) {
|
||||
function getRegionNames(line) {
|
||||
return extractRegionNames(line, /#docregion\s*(\S.*)/);
|
||||
}
|
||||
|
||||
function getEndRegionNames(line) {
|
||||
return extractRegionNames(line, /#enddocregion\s*(\S.*)/);
|
||||
}
|
||||
|
||||
function extractRegionNames(line, rx) {
|
||||
try {
|
||||
var name = line.match(/#docregion\s*(\S*).*/)[1];
|
||||
var names = line.match(rx)[1];
|
||||
names = names.replace(/\s*/g,'');
|
||||
// Hack for html regions that look like <!-- #docregion --> or */
|
||||
name = name.replace("-->","").replace('\*\/',"");
|
||||
return name;
|
||||
names = names.replace("-->","").replace('\*\/',"");
|
||||
names = names.split(',');
|
||||
return names;
|
||||
} catch (e) {
|
||||
return '';
|
||||
return [''];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
module.exports = function regionExtractor() {
|
||||
|
||||
var nullLine = '###';
|
||||
var nullLinePattern = new RegExp(nullLine + '\n', 'g');
|
||||
|
||||
// split out each fragment in {content} into a separate doc
|
||||
// a fragment is a section of text surrounded by
|
||||
// 1) In front: a comment marker followed by '#docregion' followed by an optional region name. For example:
|
||||
// <-- #docregion foo --> for html
|
||||
// or // #docregion foo for js/ts
|
||||
// 2) In back: a comment marker followed by '#enddocregion'
|
||||
// Regions can be nested and any regions not 'closed' are automatically closed at the end of the doc.
|
||||
return function(content, commentPrefixes) {
|
||||
|
||||
var lines = result = content.split(/\r?\n/);
|
||||
var docs = [];
|
||||
var docStack = [];
|
||||
var doc = null;
|
||||
|
||||
lines.forEach(function(line, ix) {
|
||||
if (isCommentLine(line, commentPrefixes)) {
|
||||
if (hasRegionTag(line)) {
|
||||
if (doc) docStack.push(doc);
|
||||
doc = {startIx: ix, regionName: getRegionName(line)};
|
||||
lines[ix] = nullLine;
|
||||
docs.push(doc);
|
||||
} else if (hasEndRegionTag(line)) {
|
||||
if (doc) {
|
||||
lines[ix] = nullLine;
|
||||
doc.endIx = ix;
|
||||
doc = docStack.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
docs.forEach(function(doc) {
|
||||
var fragLines, content;
|
||||
if (doc.endIx) {
|
||||
fragLines = lines.slice(doc.startIx + 1, doc.endIx);
|
||||
} else {
|
||||
fragLines = lines.slice(doc.startIx + 1);
|
||||
}
|
||||
fragLines = trimLeftIndent(fragLines);
|
||||
content = fragLines.join('\n');
|
||||
// eliminate all #docregion lines
|
||||
content = content.replace(nullLinePattern, '');
|
||||
if (content.substr(-3) === nullLine) {
|
||||
content = content.substr(0, content.length-3);
|
||||
}
|
||||
doc.content = content;
|
||||
});
|
||||
return docs;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
function trimLeftIndent(lines) {
|
||||
var minIx = 100;
|
||||
var ok = lines.every(function(line) {
|
||||
// var ix = line.search(/\S/);
|
||||
var ix = line.search(/[^ ]/);
|
||||
if (ix === 0) return false;
|
||||
if (ix === -1) return true;
|
||||
if (ix > 0) {
|
||||
minIx = Math.min(minIx, ix);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if ( (!ok) || minIx === 100) return lines;
|
||||
|
||||
var result = lines.map(function(line) {
|
||||
if (line.length > minIx) {
|
||||
return line.substr(minIx);
|
||||
} else {
|
||||
// this can happen if line is all blanks and shorter than mixIx
|
||||
return line;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function isCommentLine(line, commentPrefixes) {
|
||||
return commentPrefixes.some(function(prefix) {
|
||||
return line.trim().indexOf(prefix) == 0;
|
||||
});
|
||||
}
|
||||
|
||||
function hasRegionTag(line) {
|
||||
return line.indexOf("#docregion") >= 0;
|
||||
}
|
||||
|
||||
function hasEndRegionTag(line) {
|
||||
return line.indexOf("#enddocregion") >= 0;
|
||||
}
|
||||
|
||||
function getRegionName(line) {
|
||||
try {
|
||||
var name = line.match(/#docregion\s*(\S*).*/)[1];
|
||||
// Hack for html regions that look like <!-- #docregion --> or */
|
||||
name = name.replace("-->","").replace('\*\/',"");
|
||||
return name;
|
||||
} catch (e) {
|
||||
return '';
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue