Skip to content

Commit

Permalink
Add support for subsetting by section heading (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
earldouglas committed Dec 28, 2023
1 parent 0167499 commit 5f07af1
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 14 deletions.
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,8 @@ code blocks are nested within an unordered list:
## Sections and subsections

The section above is 1.3, counting by headings. It has two subsections
(1.3.1 and 1.3.2). We can specify a section to extract the content from
just that section:
(1.3.1 and 1.3.2). We can specify a section number to extract the
content from just that section:

```
$ cat README.md | codedown haskell --section 1.3
Expand All @@ -158,6 +158,14 @@ main :: IO ()
main = putStrLn $ show x
```

We can also specify a section by heading:

```
cat README.md | ./codedown.js haskell --section '### Variables in different languages'
x :: Int
x = 42
```

## Wildcard matching

Codedown can use wildcards to match file paths, which are used by some
Expand Down
41 changes: 33 additions & 8 deletions lib/codedown.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
var readline = root.readline || require('readline');
var minimatch = root.minimatch || require("minimatch");

var codedown = function(src, lang, separator, section) {
var codedown = function(src, lang, separator, targetSection) {

if (separator === undefined) {
separator = '';
Expand All @@ -26,15 +26,43 @@
}
}

var tracker = [];
var currentSectionNumber = [];
var currentSectionName = null;
var sectionNumbers = {};

var sectionNumberMatches =
function () {
return currentSectionNumber.join('.').startsWith(targetSection);
};

var sectionNameMatches =
function () {
return sectionNumbers[targetSection] &&
sectionNumbers[currentSectionName].startsWith(sectionNumbers[targetSection]);
};

var sectionMatches =
function () {
return !targetSection || sectionNumberMatches() || sectionNameMatches();
};

var languageMatches =
function (language) {
return language && minimatch(language, lang);
};

renderer.heading =
function(text, level, raw) {
var index = level - 1; // 0-based indexing
for (var i = 0; i <= index; i++) {
tracker[i] = tracker[i] || 0;
currentSectionNumber[i] = currentSectionNumber[i] || 0;
}
tracker[index] = tracker[index] + 1;
currentSectionNumber[index] = currentSectionNumber[index] + 1;
currentSectionNumber.splice(level);

currentSectionName = ('#'.repeat(level) + ' ' + raw).trim();
sectionNumbers[currentSectionName] = currentSectionNumber.join('.');

return '';
};

Expand All @@ -43,10 +71,7 @@

var result = '';

if (
language && minimatch(language, lang) &&
(!section || tracker.join('.').startsWith(section))
) {
if (languageMatches(language) && sectionMatches()) {
result = separator + src + '\n';
}

Expand Down
62 changes: 58 additions & 4 deletions test/codedown.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ describe('codedown', function(){
});
});

it('should extract code by section (1)', function (done) {
it('should extract code by section number (1)', function (done) {
process.exec('cat README.md | ./codedown.js haskell --section 1', function (err, stdout, stderr) {
if (!err) {
assert.equal(
Expand All @@ -100,7 +100,7 @@ describe('codedown', function(){
});
});

it('should extract code by section (1.3)', function (done) {
it('should extract code by section number (1.3)', function (done) {
process.exec('cat README.md | ./codedown.js haskell --section 1.3', function (err, stdout, stderr) {
if (!err) {
assert.equal(
Expand All @@ -120,7 +120,7 @@ describe('codedown', function(){
});
});

it('should extract code by section (1.3.1)', function (done) {
it('should extract code by section number (1.3.1)', function (done) {
process.exec('cat README.md | ./codedown.js haskell --section 1.3.1', function (err, stdout, stderr) {
if (!err) {
assert.equal(
Expand All @@ -137,7 +137,7 @@ describe('codedown', function(){
});
});

it('should extract code by section (1.3.2)', function (done) {
it('should extract code by section number (1.3.2)', function (done) {
process.exec('cat README.md | ./codedown.js haskell --section 1.3.2', function (err, stdout, stderr) {
if (!err) {
assert.equal(
Expand All @@ -154,4 +154,58 @@ describe('codedown', function(){
});
});

it('should extract code by section name (## Examples)', function (done) {
process.exec('cat README.md | ./codedown.js haskell --section "## Examples"', function (err, stdout, stderr) {
if (!err) {
assert.equal(
stdout,
[ 'x :: Int'
, 'x = 42'
, ''
, 'main :: IO ()'
, 'main = putStrLn $ show x'
, ''
].join('\n')
);
done();
} else {
console.log(stderr);
}
});
});

it('should extract code by section name (### Variables in different languages)', function (done) {
process.exec('cat README.md | ./codedown.js haskell --section "### Variables in different languages"', function (err, stdout, stderr) {
if (!err) {
assert.equal(
stdout,
[ 'x :: Int'
, 'x = 42'
, ''
].join('\n')
);
done();
} else {
console.log(stderr);
}
});
});

it('should extract code by section name (### Console output in different languages)', function (done) {
process.exec('cat README.md | ./codedown.js haskell --section "### Console output in different languages"', function (err, stdout, stderr) {
if (!err) {
assert.equal(
stdout,
[ 'main :: IO ()'
, 'main = putStrLn $ show x'
, ''
].join('\n')
);
done();
} else {
console.log(stderr);
}
});
});

});

0 comments on commit 5f07af1

Please sign in to comment.