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
85 changes: 47 additions & 38 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
var VFile = require('vfile')
var path = require('path')
var fs = require('fs')
var fastGlob = require('fast-glob')

var parseInclude = /^@include (.*)(\n|$)/

Expand All @@ -14,32 +15,28 @@ module.exports = function (options) {
prt.blockMethods.unshift('include')

return function transformer(ast, file) {
var children = ast.children
// look for any "include" elements

for (var i = 0; i < children.length; i++) {
var child = children[i]
var i = 0;
while (i < ast.children.length) {
var child = ast.children[i];
if (child.type === 'include') {
// Load file and create VFile
// console.log(cwd, file)
// var file = toFile(path.join(file.dirname || cwd, child.value))

// Parse vfile contents
// var parser = new processor.Parser(file, null, processor)
var root = proc.runSync(proc.parse(
toFile(path.join(child.source.dirname || cwd, child.value))
))

// Split and merge the head and tail around the new children
var head = children.slice(0, i)
var tail = children.slice(i + 1)
children = head.concat(root.children).concat(tail)

// Remember to update the offset!
i += root.children.length - 1
var includedChildren = [];

var includePattern = path.join(child.source.dirname || cwd, child.value)
var includePathsUnique = matchMdPaths(includePattern, glob=options.glob)
for (var includePath of includePathsUnique) {
var fileContents = fs.readFileSync(includePath, {encoding: "utf-8"})
var vfile = new VFile({path: includePath, contents: fileContents})
var includedChildrenFromCurrentFile = proc.runSync(proc.parse(vfile)).children;
includedChildren = includedChildren.concat(includedChildrenFromCurrentFile)
}
ast.children.splice(i, 1, ...includedChildren)
i += includedChildren.length
} else {
i ++
}
}

ast.children = children
}
}

Expand Down Expand Up @@ -70,20 +67,32 @@ function tokenizer (eat, value, silent) {
return node
}

function toFile(full) {
return new VFile({path: full, contents: loadContent(full).toString('utf8')})
}

function loadContent(file) {
// console.log('loading', file)
try { return fs.readFileSync(file) }
catch (e) {}

try { return fs.readFileSync(file + '.md') }
catch (e) {}

try { return fs.readFileSync(file + '.markdown') }
catch (e) {}

throw new Error('Unable to include ' + file)
/**
* returns an array of paths that match the given pattern
* if glob is true, find matches based on a glob pattern
* otherwise, look for "pattern", "pattern.md" or "pattern.markdown"
*/
function matchMdPaths(pattern, glob=false) {
var patterns = [pattern, pattern + ".md", pattern + ".markdown"]
if (glob) {
var includePaths = [];
for (let pat of patterns) {
includePaths = includePaths.concat(fastGlob.sync(pat))
}
// remove any duplicates that were matched
// both with and without extensions
var includePathsUnique = [...new Set(includePaths)]
includePathsUnique.sort()
if (includePaths.length === 0) {
throw new Error('Unable to include ' + pattern)
}
return includePathsUnique
} else {
for (let pat of patterns) {
if (fs.existsSync(pat)) {
return [pat]
}
}
throw new Error('Unable to include ' + pattern)
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"tap": "^10.0.0"
},
"dependencies": {
"fast-glob": "^3.2.2",
"vfile": "^2.0.0"
}
}
1 change: 1 addition & 0 deletions test/c1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# C1
1 change: 1 addition & 0 deletions test/c2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# C2
1 change: 1 addition & 0 deletions test/pattern.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@include c*.md
24 changes: 20 additions & 4 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ var tap = require('tap')
var fs = require('fs')

var include = require('../index')

var processor = remark().use(include)
var processorGlob = remark().use(include, {glob: true})

var map = {
'@include a.md': '# A',
'@include a': '# A',
'@include b': '# B',
'@include sub/sub': '# A\n\n# sub'
'@include sub/sub': '# A\n\n# sub',
'@include c*.md': '# C1\n\n# C2'
}

function transform (lines) {
Expand All @@ -31,27 +34,30 @@ function loadFile (filePath) {

tap.test('should include by exact path', function (t) {
var file = loadFile('exact.md')
var expected = transform(file.contents.split('\n'))
t.equal(
processor.processSync(file).toString(),
transform(file.contents.split('\n'))
expected
)
t.end()
})

tap.test('should include by guessing extension', function (t) {
var file = loadFile('guess.md')
var expected = transform(file.contents.split('\n'))
t.equal(
processor.processSync(file).toString(),
transform(file.contents.split('\n'))
expected
)
t.end()
})

tap.test('should include from sub and super paths', function (t) {
var file = loadFile('super.md')
var expected = transform(file.contents.split('\n'))
t.equal(
processor.processSync(file).toString(),
transform(file.contents.split('\n'))
expected
)
t.end()
})
Expand All @@ -63,3 +69,13 @@ tap.test('should fail to include non-existent file', function (t) {
)
t.end()
})

tap.test('should include by glob pattern', function(t) {
var file = loadFile('pattern.md')
var expected = transform(file.contents.split('\n'))
t.equal(
processorGlob.processSync(file).toString(),
expected
)
t.end()
})