Skip to content
This repository was archived by the owner on Nov 25, 2024. It is now read-only.

Commit 1e27d42

Browse files
author
James
authored
Merge pull request #348 from jamesramsay/get-stream
4.0-beta.1
2 parents 74dc6da + a686881 commit 1e27d42

40 files changed

Lines changed: 935 additions & 1176 deletions

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
test/fixtures/index.js
22
test/integration/_mock.js
3+
test/benchmark.js

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
node_modules
22
lib
3+
.bats
34
.coveralls.yml
45
coverage
56
.nyc_output
67
*.log
7-
test/modules*

README.md

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Hercule is a command-line tool and library for transcluding markdown, [API Bluep
2727
Install Hercule using [npm](http://npmjs.org):
2828

2929
```bash
30-
npm install -g hercule
30+
$ npm install -g hercule
3131
```
3232

3333
## Usage
@@ -41,7 +41,7 @@ hercule src/blueprint.md -o output.md
4141
Hercule supports processing input from stdin, and writing to stdout:
4242

4343
```
44-
cat src/blueprint.md | hercule | less
44+
cat src/blueprint.md | hercule - | less
4545
```
4646

4747
Or you can use Hercule as a library:
@@ -180,10 +180,7 @@ Each line of `snippet.c` will be indented with the whitespace preceding it.
180180
- [`transcludeString`](#transcludeString)
181181
- [`transcludeFile`](#transcludeFile)
182182
- [Resolvers](#resolvers)
183-
- [`defaultResolvers`](#defaultResolvers)
184-
- [`resolveHttpUrl`](#resolveHttpUrl)
185-
- [`resolveLocalUrl`](#resolveLocalUrl)
186-
- [`resolveString`](#resolveString)
183+
- [Custom Transclusion Syntax](#customSyntax)
187184

188185
---------------------------------------
189186

@@ -197,7 +194,8 @@ __Arguments__
197194

198195
1. `source` (_String_): A string used for resolving relative links and generating sourcemap.
199196
2. `options` (_Object_): An object of options to be applied when processing input.
200-
- `resolvers` - An array of functions which are applied to resolve the URLs to content.
197+
- `resolvers` (_Array[Function]_): An array of functions which are applied to resolve the URLs to content.
198+
- `transclusionSyntax` (_String_): Choose transclusion link syntax. Supports 'hercule', 'aglio', 'marked', 'multimarkdown'.
201199

202200
__Customer Emitters__
203201

@@ -233,6 +231,7 @@ __Arguments__
233231
2. `options` (_Object_): An object of options to be applied when processing input.
234232
- `source` (_String_): source file required for resolving relative links and generating sourcemap.
235233
- `resolvers` (_Array[Function]_): An array of functions which are applied to resolve the URLs to content.
234+
- `transclusionSyntax` (_String_): Choose transclusion link syntax. Supports 'hercule', 'aglio', 'marked', 'multimarkdown'.
236235
3. `callback(err, [output], [sourcemap])` (_Function_): A function that will be called after the input `str` has been processed.
237236
- `err` (_Error_): An error object.
238237
- `output` (_String_): A string containing processed input.
@@ -263,6 +262,7 @@ __Arguments__
263262
1. `source` (_String_): A path to a file to process.
264263
2. `options` (_Object_): An object of options to be applied when processing input.
265264
- `resolvers` (_Array[Function]_): An array of functions which are applied to resolve the URLs to content.
265+
- `transclusionSyntax` (_String_): Choose transclusion link syntax. Supports 'hercule', 'aglio', 'marked', 'multimarkdown'.
266266
3. `callback(err, [output], [sourcemap])` (_Function_): A function that will be called after the `source` file has been processed.
267267
- `err` (_Error_): An error object.
268268
- `output` (_String_): A string containing processed input.
@@ -297,32 +297,40 @@ __Arguments__
297297

298298
__Returns__
299299

300+
- (_null_): Returns null if the url cannot be resolved.
300301
- (_Object_)
301302
- `content` (_Stream | String_): The content to be transcluded. Streams are processed for further transclusion links. Strings are assumed fully processed.
302303
- `url` (_String_): The absolute url of the input, allowing circular reference detection and nested transclusion.
303304

304-
<a name="defaultResolvers" />
305-
306-
#### defaultResolvers
307-
308-
Ordered array of functions applied until a result is returned.
309-
310-
TODO: write the rest of this
305+
__Examples__
311306

312-
<a name="resolveHttpUrl" />
307+
```
308+
import { trancludeFile, resolveHttpUrl, resolveLocalUrl, resolveString } from 'hercule';
313309
314-
#### resolveHttpUrl
310+
function myResolver(url, source) {
311+
// Add your implementation here
312+
// Return null to try next resolver
313+
return null;
314+
}
315315
316-
TODO: write this
316+
// Resolvers are tried in order
317+
const resolvers = [myResolver, resolveHttpUrl, resolveLocalUrl, resolveString];
317318
318-
<a name="resolveLocalUrl" />
319+
trancludeFile('foo.md', { resolvers }, (err, output) => {
320+
// Handle exceptions like dead links
321+
if (err) console.log(err)
322+
console.log(output);
323+
});
324+
```
319325

320-
#### resolveLocalUrl
326+
---------------------------------------
321327

322-
TODO: write this
328+
<a name="customSyntax" />
323329

324-
<a name="resolveString" />
330+
### Custom Transclusion Syntax
325331

326-
#### resolveString
332+
Hercule also has basic support for alternative transclusion link syntax, including:
327333

328-
TODO: write this
334+
- [aglio](https://github.com/danielgtaylor/aglio/): `<!-- include(foo.md) -->`
335+
- [Marked](http://marked2app.com/help/Multi-File_Documents.html): `<<[sections/section1.md]`
336+
- [MultiMarkdown](http://fletcher.github.io/MultiMarkdown-5/transclusion.html): `{{bar.md}}`

package.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "hercule",
3-
"version": "4.0.0",
3+
"version": "4.0.0-beta.1",
44
"description": "Markdown, API Blueprint and string transclusion",
55
"main": "./lib/hercule",
66
"scripts": {
@@ -17,7 +17,8 @@
1717
"check-commit": "./scripts/commit-msg",
1818
"release:major": "npm version major && git push --follow-tags",
1919
"release:minor": "npm version minor && git push --follow-tags",
20-
"release:patch": "npm version patch && git push --follow-tags"
20+
"release:patch": "npm version patch && git push --follow-tags",
21+
"benchmark": "./test/benchmark.js"
2122
},
2223
"engines": {
2324
"node": ">=4.0.0"
@@ -66,12 +67,13 @@
6667
"dependencies": {
6768
"async": "^2.1.4",
6869
"clone-regexp": "^1.0.0",
69-
"dashdash": "^1.10.1",
7070
"duplexer3": "^0.1.4",
71+
"get-stream": "^3.0.0",
7172
"got": "^6.5.0",
7273
"isstream": "^0.1.2",
7374
"left-split": "^1.0.0",
7475
"lodash": "^4.0.0",
76+
"meow": "^3.7.0",
7577
"source-map": "^0.5.3",
7678
"through2": "^2.0.0",
7779
"through2-get": "^0.0.2"
@@ -82,6 +84,7 @@
8284
"babel-core": "^6.4.0",
8385
"babel-preset-es2015": "^6.3.13",
8486
"babel-register": "^6.9.0",
87+
"benchmark": "^2.1.3",
8588
"codecov.io": "^0.1.6",
8689
"eslint": "^3.12.0",
8790
"eslint-config-airbnb-base": "^11.0.0",

src/hercule.js

Lines changed: 18 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,39 +2,31 @@ import fs from 'fs';
22
import _ from 'lodash';
33
import duplexer from 'duplexer3';
44
import get from 'through2-get';
5+
import getStream from 'get-stream';
56

67
import Transclude from './transclude';
78
import Indent from './indent';
89
import Trim from './trim';
910
import Sourcemap from './sourcemap';
1011

12+
export { resolveHttpUrl, resolveLocalUrl, resolveString } from './resolver';
13+
1114
export function TranscludeStream(source = 'input', options) {
1215
const outputFile = _.get(options, 'outputFile');
1316
let sourceMap;
1417

15-
const transclude = new Transclude(source);
18+
const transclude = new Transclude(source, options);
1619
const indenter = new Indent();
1720
const trim = new Trim();
1821
const sourcemap = new Sourcemap(outputFile);
1922
const stringify = get('content');
2023

21-
transclude
22-
.pipe(trim)
23-
.pipe(indenter)
24-
.pipe(sourcemap)
25-
.pipe(stringify);
26-
27-
const transcluder = duplexer(transclude, stringify);
24+
transclude.on('error', () => transclude.end());
25+
sourcemap.on('sourcemap', generatedSourceMap => (sourceMap = generatedSourceMap));
2826

29-
transclude.on('error', (err) => {
30-
transcluder.emit('error', err);
31-
transclude.end();
32-
});
33-
34-
sourcemap.on('sourcemap', (generatedSourceMap) => {
35-
sourceMap = generatedSourceMap;
36-
});
27+
transclude.pipe(trim).pipe(indenter).pipe(sourcemap).pipe(stringify);
3728

29+
const transcluder = duplexer({ bubbleErrors: false }, transclude, stringify);
3830
transcluder.on('end', () => transcluder.emit('sourcemap', sourceMap));
3931

4032
return transcluder;
@@ -47,25 +39,15 @@ export function transcludeString(...args) {
4739
const source = _.get(options, 'source') || 'string';
4840

4941
const transclude = new TranscludeStream(source, options);
50-
let outputString = '';
5142
let sourceMap;
52-
let cbErr = null;
53-
54-
transclude
55-
.on('readable', function read() {
56-
let content = null;
57-
while ((content = this.read()) !== null) {
58-
outputString += content.toString('utf8');
59-
}
60-
})
61-
.on('error', (err) => {
62-
if (!cbErr) cbErr = err;
63-
})
64-
.on('sourcemap', srcmap => (sourceMap = srcmap))
65-
.on('end', () => cb(cbErr, outputString, sourceMap));
6643

44+
transclude.on('sourcemap', srcmap => (sourceMap = srcmap));
6745
transclude.write(input, 'utf8');
6846
transclude.end();
47+
48+
getStream(transclude)
49+
.then(output => cb(null, output, sourceMap))
50+
.catch(err => cb(err, err.bufferedData, sourceMap));
6951
}
7052

7153

@@ -76,24 +58,13 @@ export function transcludeFile(...args) {
7658

7759
const transclude = new TranscludeStream(input, options);
7860
const inputStream = fs.createReadStream(input, { encoding: 'utf8' });
79-
let outputString = '';
8061
let sourceMap;
81-
let cbErr = null;
8262

63+
transclude.on('sourcemap', srcmap => (sourceMap = srcmap));
8364
inputStream.on('error', err => cb(err));
84-
85-
transclude
86-
.on('readable', function read() {
87-
let content = null;
88-
while ((content = this.read()) !== null) {
89-
outputString += content;
90-
}
91-
})
92-
.on('error', (err) => {
93-
if (!cbErr) cbErr = err;
94-
})
95-
.on('sourcemap', srcmap => (sourceMap = srcmap))
96-
.on('end', () => cb(cbErr, outputString, sourceMap));
97-
9865
inputStream.pipe(transclude);
66+
67+
getStream(transclude)
68+
.then(output => cb(null, output, sourceMap))
69+
.catch(err => cb(err, err.bufferedData, sourceMap));
9970
}

src/indent.js

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
import through2 from 'through2';
22

3-
/**
4-
* Indents each line of a chunk by the provided indent amount
5-
*/
6-
73
export default function Indent() {
84
const NEWLINE = '\n';
95
const inputBuffer = [];
@@ -19,11 +15,9 @@ export default function Indent() {
1915
const beginsNewLine = inputBuffer[1].content.slice(0, 1) === NEWLINE;
2016

2117
if (indent) {
22-
if (preceededNewLine && !beginsNewLine) {
23-
content = indent + content;
24-
}
25-
content = content.replace(/\n(?!\s|$)/g, `\n${indent}`);
18+
if (preceededNewLine && !beginsNewLine) content = indent + content;
2619

20+
content = content.replace(/\n(?!\s|$)/g, `\n${indent}`);
2721
inputBuffer[1].content = content;
2822
}
2923

0 commit comments

Comments
 (0)