Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
/node_modules
/node_modules
.npmignore
npm-debug.log
30 changes: 27 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,34 @@ $ npm install hugo-lunr
```

## Options
By default hugo-lunr will read the `content` directory of you and output the lunr index to `public/lunr.json`. If you are using the command line implementation you can pass an input directory `-i` and and output path/file `-o`.
By default hugo-lunr will read the `content` directory of you and output the lunr index to `public/lunr.json`. If you are using the command line implementation you can pass an input directory `-i` and an output path/file `-o`.

### Exclude folders

To exclude folders within your input directory, you can pass comma-separated [glob patterns](https://www.npmjs.com/package/glob#glob-primer) with the `--excludes` parameter, e.g.

```
hugo-lunr -i \"content/subdir/**\" -o public/my-index.json --excludes \"content/images/**\"
```

Note that the API version of this flag (`setExcludes()`) can accept a comma-separated string or an array of glob patterns.

### Content file options

Using the `--fileopts` CLI flag or `setFileOpts()` API method, you can specify these options when reading content files:

| Key | Default | Desc |
| --- | --- | --- |
| `matter` | `{delims: '+++', lang:'toml'}` | [Options](https://www.npmjs.com/package/gray-matter#read) for reading front matter |
| `taxonomies` | `['tags']` | Array of taxonomies to include in index |
| `indexDrafts` | `false` | Whether to include draft posts when building search index. Note that **future-dated posts will be indexed** (PRs welcome...) |
| `params` | `[]` | Array of any other parameters to include in index, e.g. `date` |
| `callback` | null | Callback function to transform the output of reading each file. Can be used only with API |

You can provide the path to a JSON file using CLI flag or API, or just pass an object directly when calling the API method.

## How to use hugo-lunr CLI

The easiest way to use hugo-lunr is via npm scripts:
```
"scripts": {
Expand Down Expand Up @@ -48,7 +72,7 @@ var hugolunr = require('hugo-lunr');
var h = new hugolunr();
h.setInput('content/faq/**');
h.setOutput('public/faq.json');
h.setExcludes(['content/faq/images/**', 'content/faq/subdir/assets/**']);
h.setFileOpts({ taxonomies: ['tags', 'categories'] });
h.index();
```


102 changes: 79 additions & 23 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ function HugoLunr(input, output){
//defaults
this.input = 'content/**';
this.output = 'public/lunr.json';
this.excludes = [];

// Default file reading options
this.fileOpts = {
matter: {delims: '+++', lang:'toml'},
taxonomies: ['tags'],
indexDrafts: false,
params: [],
callback: null
};

if(process.argv.indexOf("-o") != -1){ //does output flag exist?
this.setOutput(process.argv[process.argv.indexOf("-o") + 1]); //grab the next item
Expand All @@ -30,17 +40,56 @@ function HugoLunr(input, output){
this.setInput(process.argv[process.argv.indexOf("-i") + 1]); //grab the next item
}

if(process.argv.indexOf("--excludes") != -1){ //does excludes flag exist?
this.setExcludes(process.argv[process.argv.indexOf("--excludes") + 1]); //grab the next item
}

if(process.argv.indexOf("--fileopts") != -1){ //does fileopts flag exist?
this.setFileOpts(process.argv[process.argv.indexOf("--fileopts") + 1]); //grab the next item
}

this.baseDir = path.dirname(this.input);
}

HugoLunr.prototype.setInput = function(input) {
this.input = input;
this.baseDir = path.dirname(input);
}

HugoLunr.prototype.setOutput = function(output) {
this.output = output;
}

HugoLunr.prototype.setExcludes = function(excludes) {
// Comma-separated array of glob paths from --excludes arg
// Or array if using API
this.excludes = typeof excludes === 'string' ? excludes.split(',') : excludes;
}

HugoLunr.prototype.setFileOpts = function(opts) {
// If string assume path to opts JSON file
// otherwise assume object was passed to API
var optsObj = opts;
if ('string' === typeof opts) {
try {
var filename = path.resolve(path.dirname(process.argv[1]), opts);
optsObj = JSON.parse(fs.readFileSync(filename, 'utf8'));
} catch (e) {
optsObj = null;
}
}

if (!optsObj) {
return;
}

// Merge into this.fileOpts
var self = this;
Object.keys(optsObj).forEach(function(key) {
self.fileOpts[key] = optsObj[key];
});
}

HugoLunr.prototype.index = function(input, output){
var self = this;

Expand All @@ -62,7 +111,7 @@ HugoLunr.prototype.index = function(input, output){

HugoLunr.prototype.readDirectory = function(path){
var self = this;
var files = glob.sync(path);
var files = glob.sync(path, { ignore: this.excludes });
var len = files.length;
for (var i=0;i<len;i++){
var stats = fs.lstatSync(files[i]);
Expand All @@ -76,39 +125,46 @@ HugoLunr.prototype.readDirectory = function(path){
HugoLunr.prototype.readFile = function(filePath){
var self = this;
var ext = path.extname(filePath);
var meta = matter.read(filePath, {delims: '+++', lang:'toml'});
if (meta.data.draft === true){
var meta = matter.read(filePath, self.fileOpts.matter);
if (meta.data.draft === true && !self.fileOpts.indexDrafts){
return;
}

if (ext == '.md'){
var plainText = removeMd(meta.content);
// Setup title and content
var item = {
title: meta.data.title || '',
content: ext == '.md' ? removeMd(meta.content) : striptags(meta.content)
};

// Setup URI
if (meta.data.url != undefined){
item.uri = meta.data.url;
} else {
var plainText = striptags(meta.content);
}
var uri = '/' + filePath.substring(0,filePath.lastIndexOf('.'));
uri = uri.replace(self.baseDir +'/', '');

var uri = '/' + filePath.substring(0,filePath.lastIndexOf('.'));
uri = uri.replace(self.baseDir +'/', '');
if (meta.data.slug != undefined){
uri = path.dirname(uri) + meta.data.slug;
}

if (meta.data.slug != undefined){
uri = path.dirname(uri) + meta.data.slug;
item.uri = uri;
}

if (meta.data.url != undefined){
uri = meta.data.url
}
// Setup taxonomies
self.fileOpts.taxonomies.forEach(function(taxonomy) {
item[taxonomy] = meta.data[taxonomy] || [];
});

var tags = [];
// Setup additional specified params
if (self.fileOpts.params.length) {
self.fileOpts.params.forEach(function(param) {
item[param] = meta.data[param] || null;
});
}

if (meta.data.tags != undefined){
tags = meta.data.tags;
if ('function' === typeof self.fileOpts.callback) {
item = self.fileOpts.callback(item);
}

var item = {'uri' : uri , 'title' : meta.data.title, 'content':plainText, 'tags':tags};
self.list.push(item);
}