Skip to content

Commit

Permalink
feat(search): Searching in the text of each section
Browse files Browse the repository at this point in the history
closes #2
  • Loading branch information
bahmutov committed Dec 1, 2015
1 parent 871a060 commit 3136447
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 15 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"semantic-release": "semantic-release pre && npm publish && semantic-release post",
"next-update": "next-update -k true",
"example-npm": "node ./bin/manpm.js chalk background",
"test-search-in-text": "node ./bin/manpm.js chalk cmder",
"example-github": "node ./bin/manpm.js https://github.com/bahmutov/object-fitter",
"example-es6-docs": "node ./bin/manpm.js bevacqua/es6 literals"
},
Expand Down Expand Up @@ -50,7 +51,6 @@
"debug": "2.2.0",
"get-package-readme": "1.1.0",
"lazy-ass": "1.1.0",
"lunr": "0.6.0",
"marked": "0.3.5",
"marked-terminal": "https://github.com/mikaelbr/marked-terminal.git#35f6ddac9d9f32b11e85ceb6bc5f42642f06e456",
"marked-to-md": "1.0.1",
Expand All @@ -67,7 +67,8 @@
"npm test",
"npm run example-npm",
"npm run example-github",
"npm run example-es6-docs"
"npm run example-es6-docs",
"npm run test-search-in-text"
],
"pre-push": [
"npm run size",
Expand Down
27 changes: 19 additions & 8 deletions src/find-section-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ var describeIt = require('describe-it');
var marked = require('marked');
var quote = require('quote');

/* global describe, it */

describeIt(partJs, 'findSectionByHeader(search, tokens)', function () {
it('is a function', function () {
la(check.fn(this.findSectionByHeader));
Expand Down Expand Up @@ -62,18 +64,14 @@ describeIt(partJs, 'findSectionByHeader(search, tokens)', function () {
});
});

describeIt(partJs, 'markdownTokens(md)', function () {
describeIt(partJs, 'var toTokens', function () {
it('is a function', function () {
la(check.fn(this.markdownTokens));
});

it('expects single argument', function () {
la(this.markdownTokens.length === 1);
la(check.fn(this.toTokens));
});

it('parses 2 paragraphs', function () {
var text = ['# p1', 'foo', '# p2', 'bar'].join('\n');
var tokens = this.markdownTokens(text);
var tokens = this.toTokens(text);
la(check.array(tokens));
la(tokens.length === 4);

Expand All @@ -91,7 +89,6 @@ describeIt(partJs, 'markdownTokens(md)', function () {
});
});

/* global describe, it */
describe('find section', function () {
var find = require('./find-section');

Expand Down Expand Up @@ -131,4 +128,18 @@ describe('find section', function () {
var firstSection = text.slice(0, 2).join('\n');
la(found === firstSection, 'found\n' + quote(found), '\ninstead of\n' + quote(firstSection));
});

it('finds word inside the section', function () {
var text = [
'# 1 is foo',
'foo is awesome',
'# 2 is bar',
'bar is not as good'
];
var search = { text: 'awesome' };
var expected = text.slice(0, 2).join('\n');
var found = find(search, text.join('\n'));
la(check.unemptyString(found), 'could not find', search);
la(found === expected, 'found first section\n' + found);
});
});
58 changes: 53 additions & 5 deletions src/find-section.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,24 @@ var marked = require('marked');
var mdRenderer = require('marked-to-md');
var renderer = mdRenderer(new marked.Renderer());
var parser = new marked.Parser({ renderer: renderer });
var toSections = require('./to-sections');
var _ = require('lodash');

function markdownTokens(md) {
var tokens = marked.lexer(md);
return tokens;
var toTokens = marked.lexer.bind(marked);

function fromTokens(tokens) {
// parser.parse removes all items from tokens!
var copy = _.clone(tokens, true);
copy.links = _.clone(tokens.links, true);
return parser.parse(copy);
}

// assumes search is lowercase text already
function hasText(text, search) {
la(check.string(text), 'missing text', text);
la(check.unemptyString(search), 'missing search', search);
var has = text.toLowerCase().indexOf(search) !== -1;
return has;
}

// returns found tokens
Expand Down Expand Up @@ -69,6 +83,33 @@ function findSectionByHeader(search, tokens) {
return foundTokens;
}

// returns found tokens
function findSectionByText(search, tokens) {
la(check.unemptyString(search), 'missing search', search);
la(check.array(tokens), 'missing tokens', tokens);

search = search.toLowerCase();

var sections = toSections(tokens);
la(check.array(sections),
'could not find sections from tokens', tokens);

var sectionsText = sections.map(fromTokens);

var foundIndex = -1;
sectionsText.some(function (sectionText, k) {
if (hasText(sectionText, search)) {
foundIndex = k;
return true;
}
});

if (foundIndex !== -1) {
return sections[foundIndex];
}
}

// if not found, returns entire text
function findSection(options, md) {
la(check.maybe.object(options), 'missing options', options);
la(check.unemptyString(md), 'missing markdown', md);
Expand All @@ -83,10 +124,17 @@ function findSection(options, md) {
return md;
}

var tokens = markdownTokens(md);
var tokens = toTokens(md);
la(check.array(tokens), 'could not parse markdown', md);

var foundSectionByHeader = findSectionByHeader(searchString, tokens);
if (check.unemptyArray(foundSectionByHeader)) {
return parser.parse(foundSectionByHeader).trim();
return fromTokens(foundSectionByHeader).trim();
}

var foundSectionByText = findSectionByText(searchString, tokens);
if (check.unemptyArray(foundSectionByText)) {
return fromTokens(foundSectionByText).trim();
}

return md;
Expand Down
43 changes: 43 additions & 0 deletions src/to-sections-spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
var la = require('lazy-ass');
var check = require('check-more-types');
var marked = require('marked');

/* global describe, it */

var toTokens = marked.lexer.bind(marked);

describe('to-sections', function () {
var toSections = require('./to-sections');

var text = [
'# 1 is foo',
'foo is awesome',
'# 2 is bar',
'bar is not as good'
].join('\n');
var tokens = toTokens(text);
la(check.array(tokens));

it('is a function', function () {
la(check.fn(toSections));
});

it('splits into 2 sections', function () {
var sections = toSections(tokens);
la(check.array(sections), sections);
la(sections.length === 2, 'found 2 sections', sections);
});

it('first section has 2 items', function () {
var sections = toSections(tokens);
var first = sections[0];
la(check.array(first), 'missing first section', first);
la(first.length === 2, 'first has 2 tokens', first);
});

it('first section has links', function () {
var sections = toSections(tokens);
var first = sections[0];
la(first.links, 'first section is missing links', first);
});
});
29 changes: 29 additions & 0 deletions src/to-sections.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
var la = require('lazy-ass');
var check = require('check-more-types');

function toSections(tokens) {
la(check.array(tokens), 'expected markdown tokens list', tokens);

var foundSections = [], current;
tokens.forEach(function (token) {
if (token.type === 'heading') {
if (current) {
foundSections.push(current);
}
current = [token];
return;
} else if (current) {
current.push(token);
}
});
if (current) {
foundSections.push(current);
}

foundSections.forEach(function (section) {
section.links = tokens.links;
});
return foundSections;
}

module.exports = toSections;

0 comments on commit 3136447

Please sign in to comment.