├── .gitignore
├── test
├── fixture
│ ├── src
│ │ └── index.md
│ └── build
│ │ └── index.html
└── index.js
├── Makefile
├── History.md
├── Readme.md
├── package.json
└── lib
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/test/fixture/src/index.md:
--------------------------------------------------------------------------------
1 |
2 | # one one
3 |
4 | ## two one
5 |
6 | # one two
7 |
8 | ## two two
9 |
10 | ### three
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 |
2 | node_modules: package.json
3 | @npm install
4 |
5 | test: node_modules
6 | @./node_modules/.bin/mocha --reporter spec
7 |
8 | .PHONY: test
--------------------------------------------------------------------------------
/test/fixture/build/index.html:
--------------------------------------------------------------------------------
1 |
one one
2 | two one
3 | one two
4 | two two
5 | three
6 |
--------------------------------------------------------------------------------
/History.md:
--------------------------------------------------------------------------------
1 |
2 | 0.2.0 / 2017-07-27
3 | ==================
4 |
5 | * fix(sorting): Fixes the return type being ordered by selector, not position in document (#5)
6 |
7 | 0.1.0 - July 11, 2015
8 | ---------------------
9 | * add `tag` metadata to headings
10 |
11 | 0.0.1 - April 2, 2014
12 | ---------------------
13 | :sparkles:
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 |
2 | # metalsmith-headings
3 |
4 | A Metalsmith plugin that extracts headings from HTML files and attaches them to the file's metadata.
5 |
6 | ## Installation
7 |
8 | $ npm install metalsmith-headings
9 |
10 | ## Example
11 |
12 | ```js
13 | var Metalsmith = require('metalsmith');
14 | var headings = require('metalsmith-headings');
15 |
16 | Metalsmith(__dirname)
17 | .use(headings('h2'))
18 | .build();
19 | ```
20 |
21 | ## License
22 |
23 | MIT
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "metalsmith-headings",
3 | "description": "A Metalsmith plugin that extracts headings from HTML files and attaches them to the file's metadata.",
4 | "repository": "git://github.com/segmentio/metalsmith-headings.git",
5 | "version": "0.2.0",
6 | "license": "MIT",
7 | "main": "lib/index.js",
8 | "scripts": {
9 | "test": "mocha --reporter spec"
10 | },
11 | "dependencies": {
12 | "cheerio": "^0.14.0"
13 | },
14 | "devDependencies": {
15 | "mocha": "1.x",
16 | "metalsmith": "0.x",
17 | "metalsmith-markdown": "^0.2.1"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 |
2 | var cheerio = require('cheerio');
3 | var extname = require('path').extname;
4 |
5 | /**
6 | * Expose `plugin`.
7 | */
8 |
9 | module.exports = plugin;
10 |
11 | /**
12 | * Get the headings from any html files.
13 | *
14 | * @param {String or Object} options (optional)
15 | * @property {Array} selectors
16 | */
17 |
18 | function plugin(options){
19 | if ('string' == typeof options) options = { selectors: [options] };
20 | options = options || {};
21 | var selectors = options.selectors || ['h2'];
22 |
23 | return function(files, metalsmith, done){
24 | setImmediate(done);
25 | Object.keys(files).forEach(function(file){
26 | if ('.html' != extname(file)) return;
27 | var data = files[file];
28 | var contents = data.contents.toString();
29 | var $ = cheerio.load(contents);
30 | data.headings = [];
31 |
32 | $(selectors.join(',')).each(function(){
33 | data.headings.push({
34 | id: $(this).attr('id'),
35 | tag: $(this)[0].name,
36 | text: $(this).text()
37 | });
38 | });
39 | });
40 | };
41 | }
--------------------------------------------------------------------------------
/test/index.js:
--------------------------------------------------------------------------------
1 |
2 | var assert = require('assert');
3 | var Metalsmith = require('metalsmith');
4 | var markdown = require('metalsmith-markdown');
5 | var headings = require('..');
6 |
7 | describe('metalsmith-headings', function(){
8 | it('should parse headings from HTML', function(done){
9 | Metalsmith('test/fixture')
10 | .use(markdown())
11 | .use(headings({ selectors: ['h2'] }))
12 | .build(function(err, files){
13 | if (err) return done(err);
14 | assert.deepEqual(files['index.html'].headings, [
15 | { id: 'two-one', tag: 'h2', text: 'two one' },
16 | { id: 'two-two', tag: 'h2', text: 'two two' }
17 | ]);
18 | done();
19 | });
20 | });
21 |
22 | it('should accept a string shorthand', function(done){
23 | Metalsmith('test/fixture')
24 | .use(markdown())
25 | .use(headings('h2'))
26 | .build(function(err, files){
27 | if (err) return done(err);
28 | assert.deepEqual(files['index.html'].headings, [
29 | { id: 'two-one', tag: 'h2', text: 'two one' },
30 | { id: 'two-two', tag: 'h2', text: 'two two' }
31 | ]);
32 | done();
33 | });
34 | });
35 |
36 | it('should preserve order with multiple selectors', function(done){
37 | Metalsmith('test/fixture')
38 | .use(markdown())
39 | .use(headings({ selectors: ['h1', 'h2']}))
40 | .build(function(err, files){
41 | if (err) return done(err);
42 | assert.deepEqual(files['index.html'].headings, [
43 | { id: 'one-one', tag: 'h1', text: 'one one' },
44 | { id: 'two-one', tag: 'h2', text: 'two one' },
45 | { id: 'one-two', tag: 'h1', text: 'one two' },
46 | { id: 'two-two', tag: 'h2', text: 'two two' }
47 | ]);
48 | done();
49 | });
50 | });
51 | });
52 |
--------------------------------------------------------------------------------