git.iko.soy/typeable/remark-validate-links
on main help sign in
26 files changed+1329−887
since splitsnapshots
unifiedsplit
.prettierignore+2 .travis.yml+1−1 lib/check/check-files.js+1−1 lib/find/config.js+12−1 lib/find/find.js+126−24 lib/find/index.js+1−4 lib/index.js+1−1 package.json+26−19 readme.md+51−27 test/fixtures/bitbucket.md+5−5 test/fixtures/examples/bitbucket.md+5−5 test/fixtures/examples/github.md+5−5 test/fixtures/examples/gitlab.md+5−5 test/fixtures/file-as-folder.md+1 test/fixtures/folder-without-readme/example.md+1 test/fixtures/folder.md+23 test/fixtures/folder/example.md+1 test/fixtures/folder/readme.asc+9 test/fixtures/folder/readme.markdown+5 test/fixtures/folder/readme.md+1 test/fixtures/github.md+11−7 test/fixtures/gitlab.md+9−5 test/fixtures/images.md+4−4 test/fixtures/line-links.md+2−2 test/fixtures/self-hosted.md+2−2 test/index.js+1019−769
.prettierignore+2
@@ -1 +1,3 @@
11coverage/
2+*.json
3+*.md
.travis.yml+1−1
@@ -1,5 +1,5 @@
11language: node_js
22node_js:
3− - lts/carbon
3+ - lts/dubnium
44 - node
55after_success: bash <(curl -s https://codecov.io/bash)
lib/check/check-files.js+1−1
@@ -30,7 +30,7 @@ function checkIfReferencedFilesExist(ctx, next) {
3030 fs.access(filePath, fs.F_OK, onaccess)
3131
3232 function onaccess(err) {
33− var noEntry = err && err.code === 'ENOENT'
33+ var noEntry = err && (err.code === 'ENOENT' || err.code === 'ENOTDIR')
3434
3535 landmarks[filePath] = {'': !noEntry}
3636
lib/find/config.js+12−1
@@ -6,6 +6,7 @@ module.exports = config
66
77var viewPaths = {github: 'blob', gitlab: 'blob', bitbucket: 'src'}
88var headingPrefixes = {github: '#', gitlab: '#', bitbucket: '#markdown-header-'}
9+var topAnchors = {github: '#readme', gitlab: '#readme'}
910var lineLinks = {github: true, gitlab: true}
1011
1112function config(ctx) {
@@ -17,7 +18,13 @@ function config(ctx) {
1718 return
1819 }
1920
20− urlConfig = {prefix: '', headingPrefix: '#', lines: false, hostname: null}
21+ urlConfig = {
22+ prefix: '',
23+ headingPrefix: '#',
24+ lines: false,
25+ hostname: null,
26+ topAnchor: null
27+ }
2128
2229 if (repo) {
2330 info = hostedGitInfo.fromUrl(repo)
@@ -36,6 +43,10 @@ function config(ctx) {
3643 urlConfig.lines = lineLinks[info.type]
3744 }
3845
46+ if (info.type in topAnchors) {
47+ urlConfig.topAnchor = topAnchors[info.type]
48+ }
49+
3950 urlConfig.hostname = info.domain
4051 }
4152
lib/find/find.js+126−24
@@ -1,5 +1,6 @@
11'use strict'
22
3+var fs = require('fs')
34var path = require('path')
45var URL = require('url').URL // Node 8 support
56var vfile = require('to-vfile')
@@ -21,14 +22,21 @@ var slashes = '//'
2122
2223var lineExpression = /^#l\d/i
2324
24−function find(ctx) {
25+// List from: https://github.com/github/markup#markups
26+var readmeExtensions = ['.markdown', '.mdown', '.mkdn', '.md']
27+var readmeBasename = /^readme$/i
28+
29+function find(ctx, next) {
2530 var file = ctx.file
2631 var fileSet = ctx.fileSet
2732 var absolute = file.path ? path.resolve(file.cwd, file.path) : ''
2833 var space = file.data
2934 var references = {}
3035 var landmarks = {}
31− var alreadyAdded = []
36+ var actual = 0
37+ var expected = 0
38+ var statted = []
39+ var added = []
3240 var config = xtend(ctx.urlConfig, {
3341 path: absolute,
3442 base: absolute ? path.dirname(absolute) : file.cwd,
@@ -38,18 +46,21 @@ function find(ctx) {
3846 space[constants.referenceId] = references
3947 space[constants.landmarkId] = landmarks
4048
41− landmarks[absolute] = {'': true}
49+ addLandmarks(absolute, '')
4250
4351 slugs.reset()
4452
4553 visit(ctx.tree, mark)
4654
55+ if (expected === 0) {
56+ next()
57+ }
58+
4759 function mark(node) {
4860 var data = node.data || {}
4961 var props = data.hProperties || {}
5062 var id = props.name || props.id || data.id
5163 var info = node.url ? urlToPath(node.url, config) : null
52− var refs
5364 var fp
5465 var hash
5566
@@ -58,34 +69,114 @@ function find(ctx) {
5869 }
5970
6071 if (id) {
61− landmarks[absolute][id] = true
72+ addLandmarks(absolute, id)
6273 }
6374
6475 if (info) {
6576 fp = info.filePath
6677 hash = info.hash
67− refs = references[fp] || (references[fp] = {})
6878
69− add('', node)
79+ addReference(fp, '', node)
7080
71− // With a heading
7281 if (hash) {
7382 if (fileSet || fp === absolute) {
74− add(hash, node)
83+ addReference(fp, hash, node)
7584 }
7685
77− if (fileSet && fp && alreadyAdded.indexOf(fp) === -1) {
78− alreadyAdded.push(fp)
79− fileSet.add(vfile({cwd: file.cwd, path: path.relative(file.cwd, fp)}))
86+ if (fileSet && fp && statted.indexOf(fp) === -1) {
87+ addFile(fp)
8088 }
8189 }
8290 }
91+ }
92+
93+ function addLandmarks(filePath, hash) {
94+ addLandmark(filePath, hash)
95+
96+ // Note: this may add marks too many anchors as defined.
97+ // For example, if there is both a `readme.md` and a `readme.markdown` in a
98+ // folder, both their landmarks will be defined for their parent folder.
99+ // To solve this, we could check whichever sorts first, and ignore the
100+ // others.
101+ // This is an unlikely scenario though, and adds a lot of complexity, so
102+ // we’re ignoring it.
103+ if (readme(filePath)) {
104+ addLandmark(path.dirname(filePath), hash)
105+ }
106+ }
107+
108+ function addLandmark(filePath, hash) {
109+ var marks = landmarks[filePath] || (landmarks[filePath] = {})
110+
111+ marks[hash] = true
112+ }
83113
84− function add(hash, node) {
85− if (refs[hash]) {
86− refs[hash].push(node)
114+ function addReference(filePath, hash, node) {
115+ var refs = references[filePath] || (references[filePath] = {})
116+ var hashes = refs[hash] || (refs[hash] = [])
117+
118+ hashes.push(node)
119+ }
120+
121+ function addFile(fileOrFolderPath) {
122+ expected++
123+
124+ statted.push(fileOrFolderPath)
125+
126+ fs.stat(fileOrFolderPath, onstat)
127+
128+ function onstat(_, stats) {
129+ if (stats && stats.isDirectory()) {
130+ fs.readdir(fileOrFolderPath, onreaddir)
87131 } else {
88− refs[hash] = [node]
132+ done(fileOrFolderPath)
133+ }
134+ }
135+
136+ function onreaddir(_, entries) {
137+ /* istanbul ignore next - unlikely that it is an unreadable directory. */
138+ var files = (entries || []).sort()
139+ var length = files.length
140+ var index = -1
141+ var entry
142+ var file
143+ var filePath
144+
145+ while (++index < length) {
146+ entry = entries[index]
147+
148+ if (readme(entry)) {
149+ file = entry
150+ break
151+ }
152+ }
153+
154+ // If there is no readme that we can parse, add the directory.
155+ filePath = fileOrFolderPath
156+
157+ // To do: test for no readme in directory.
158+
159+ if (file) {
160+ filePath = path.join(fileOrFolderPath, file)
161+ statted.push(filePath)
162+ }
163+
164+ done(filePath)
165+ }
166+
167+ function done(filePath) {
168+ if (added.indexOf(filePath) === -1) {
169+ added.push(filePath)
170+
171+ fileSet.add(
172+ vfile({cwd: file.cwd, path: path.relative(file.cwd, filePath)})
173+ )
174+ }
175+
176+ actual++
177+
178+ if (actual === expected) {
179+ next()
89180 }
90181 }
91182 }
@@ -96,7 +187,7 @@ function urlToPath(value, config) {
96187 var questionMarkIndex
97188 var numberSignIndex
98189
99− // Absolute paths: `/wooorm/test/blob/master/directory/example.md`.
190+ // Absolute paths: `/wooorm/test/blob/main/directory/example.md`.
100191 if (value.charAt(0) === slash) {
101192 if (!config.hostname) {
102193 return
@@ -108,9 +199,9 @@ function urlToPath(value, config) {
108199
109200 try {
110201 url = new URL(value)
111− } catch (error) {}
202+ } catch (_) {}
112203
113− // URLs: `https://github.com/wooorm/test/blob/master/directory/example.md`.
204+ // URLs: `https://github.com/wooorm/test/blob/main/directory/example.md`.
114205 if (url) {
115206 // Exit if we don’t have hosted Git info or this is not a URL to the repo.
116207 if (
@@ -129,10 +220,7 @@ function urlToPath(value, config) {
129220 // the `foo/bar` branch, or, `baz` in the `bar` directory on the `foo`
130221 // branch.
131222 // Currently, we’re ignoring this and just not supporting branches.
132− value = value
133− .split(slash)
134− .slice(1)
135− .join(slash)
223+ value = value.split(slash).slice(1).join(slash)
136224
137225 return normalize(path.resolve(config.root, value + url.hash), config)
138226 }
@@ -167,6 +255,7 @@ function normalize(url, config) {
167255 var numberSignIndex = url.indexOf(numberSign)
168256 var lines = config.lines
169257 var prefix = config.headingPrefix
258+ var topAnchor = config.topAnchor
170259 var filePath
171260 var hash
172261
@@ -176,9 +265,13 @@ function normalize(url, config) {
176265 filePath = url.slice(0, numberSignIndex)
177266 hash = url.slice(numberSignIndex).toLowerCase()
178267
268+ // Ignore the hash if it references the top anchor of the environment
269+ if (topAnchor && hash === topAnchor) {
270+ hash = undefined
271+ }
179272 // Ignore the hash if it references lines in a file or doesn’t start
180273 // with a heading prefix.
181− if (
274+ else if (
182275 (lines && lineExpression.test(hash)) ||
183276 hash.slice(0, prefix.length) !== prefix
184277 ) {
@@ -192,3 +285,12 @@ function normalize(url, config) {
192285
193286 return {filePath: decodeURIComponent(filePath), hash: hash}
194287}
288+
289+function readme(filePath) {
290+ var ext = path.extname(filePath)
291+
292+ return (
293+ readmeExtensions.indexOf(ext) !== -1 &&
294+ readmeBasename.test(path.basename(filePath, ext))
295+ )
296+}
lib/find/index.js+1−4
@@ -5,7 +5,4 @@ var findRepo = require('./find-repo')
55var config = require('./config')
66var find = require('./find')
77
8−module.exports = trough()
9− .use(findRepo)
10− .use(config)
11− .use(find)
8+module.exports = trough().use(findRepo).use(config).use(find)
lib/index.js+1−1
@@ -42,7 +42,7 @@ function cliCompleter(set, next) {
4242
4343function checkAll(files, next) {
4444 // Check all references and landmarks.
45− check.run({files: files}, function(err) {
45+ check.run({files: files}, function (err) {
4646 next(err)
4747 })
4848}
package.json+26−19
@@ -1,11 +1,12 @@
11{
22 "name": "remark-validate-links",
3− "version": "8.0.3",
3+ "version": "10.0.2",
44 "description": "remark plugin to validate links to headings and files",
55 "license": "MIT",
66 "keywords": [
77 "unified",
88 "remark",
9+ "remark-plugin",
910 "plugin",
1011 "mdast",
1112 "markdown",
@@ -17,6 +18,10 @@
1718 ],
1819 "repository": "remarkjs/remark-validate-links",
1920 "bugs": "https://github.com/remarkjs/remark-validate-links/issues",
21+ "funding": {
22+ "type": "opencollective",
23+ "url": "https://opencollective.com/unified"
24+ },
2025 "author": "Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)",
2126 "contributors": [
2227 "Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)",
@@ -28,38 +33,37 @@
2833 "Anton Rybochkin <anton.rybochkin@axibase.com>"
2934 ],
3035 "browser": {
31− "lib/check/check-files.js": "lib/check/check-files.browser.js",
32− "lib/find/find-repo.js": "lib/find/find-repo.browser.js"
36+ "./lib/check/check-files.js": "./lib/check/check-files.browser.js",
37+ "./lib/find/find-repo.js": "./lib/find/find-repo.browser.js"
3338 },
3439 "files": [
3540 "lib/",
3641 "index.js"
3742 ],
3843 "dependencies": {
39− "github-slugger": "^1.2.0",
40− "hosted-git-info": "^2.5.0",
41− "mdast-util-to-string": "^1.0.4",
44+ "github-slugger": "^1.0.0",
45+ "hosted-git-info": "^3.0.0",
46+ "mdast-util-to-string": "^1.0.0",
4247 "propose": "0.0.5",
48+ "to-vfile": "^6.0.0",
4349 "trough": "^1.0.0",
44− "unist-util-visit": "^1.0.0",
50+ "unist-util-visit": "^2.0.0",
4551 "xtend": "^4.0.0"
4652 },
4753 "devDependencies": {
48− "execa": "^1.0.0",
49− "nyc": "^14.0.0",
50− "prettier": "^1.0.0",
51− "remark": "^10.0.0",
52− "remark-cli": "^6.0.0",
53− "remark-preset-wooorm": "^5.0.0",
54− "rimraf": "^2.0.0",
55− "strip-ansi": "^5.0.0",
56− "tape": "^4.0.0",
57− "to-vfile": "^6.0.0",
54+ "nyc": "^15.0.0",
55+ "prettier": "^2.0.0",
56+ "remark": "^12.0.0",
57+ "remark-cli": "^8.0.0",
58+ "remark-preset-wooorm": "^7.0.0",
59+ "rimraf": "^3.0.0",
60+ "strip-ansi": "^6.0.0",
61+ "tape": "^5.0.0",
5862 "vfile-sort": "^2.0.0",
59− "xo": "^0.24.0"
63+ "xo": "^0.32.0"
6064 },
6165 "scripts": {
62− "format": "remark *.md -qfo && prettier --write \"**/*.js\" && xo --fix",
66+ "format": "remark . -qfo --ignore-pattern test/ && prettier . --write && xo --fix",
6367 "test-api": "node test",
6468 "test-coverage": "nyc --reporter lcov tape test/index.js",
6569 "test": "npm run format && npm run test-coverage"
@@ -82,6 +86,9 @@
8286 "prettier": true,
8387 "esnext": false,
8488 "rules": {
89+ "unicorn/prefer-optional-catch-binding": "off",
90+ "unicorn/no-fn-reference-in-iterator": "off",
91+ "unicorn/prefer-includes": "off",
8592 "guard-for-in": "off"
8693 }
8794 },
readme.md+51−27
@@ -10,20 +10,22 @@
1010
1111[**remark**][remark] plugin to validate that Markdown links and images reference
1212existing local files and headings.
13−It does not check external URLs (see [`remark-lint-no-dead-urls`][no-dead-urls]
14−for that).
1513
1614For example, this document does not have a heading named `Hello`.
17−So if we link to that (`[welcome](#hello)`), this plugin will warn about it.
15+So if we’d link to it (`[welcome](#hello)`), we’d get a warning.
1816
1917In addition, when there’s a link to a heading in another document
20−(`examples/foo.md#hello`), if this file exists but the heading does not, or if
21−the file does not exist, this plugin will also warn.
18+(`examples/foo.md#hello`), if that file exists but the heading does not, or if
19+that file does not exist, we’d also get a warning.
2220
2321Linking to other files, such as `license` or `index.js` (when they exist) is
2422fine.
2523
26−## Table of Contents
24+This plugin does not check external URLs (see
25+[`remark-lint-no-dead-urls`][no-dead-urls]) or undefined references
26+(see [`remark-lint-no-undefined-references`][no-undef-refs]).
27+
28+## Contents
2729
2830* [Install](#install)
2931* [Use](#use)
@@ -31,6 +33,7 @@ fine.
3133 * [API](#api)
3234* [Configuration](#configuration)
3335* [Integration](#integration)
36+* [Security](#security)
3437* [Related](#related)
3538* [Contribute](#contribute)
3639* [License](#license)
@@ -62,7 +65,7 @@ Read more [whoops, this does not exist](#world).
6265
6366This doesn’t exist either [whoops!](readme.md#foo).
6467
65−But this does exist: [LICENSE](LICENSE).
68+But this does exist: [license](license).
6669
6770So does this: [README](readme.md#installation).
6871```
@@ -93,17 +96,22 @@ Say we have the following file, `example.md`:
9396```markdown
9497# Alpha
9598
99+Links are checked:
100+
96101This [exists](#alpha).
97102This [one does not](#does-not).
98−References and definitions are [checked][alpha] [too][charlie].
99103
100104# Bravo
101105
102−Headings in `readme.md` are [not checked](readme.md#bravo).
103−But [missing files are reported](missing-example.js).
106+Headings in `readme.md` are [checked](readme.md#nosuchheading).
107+And [missing files are reported](missing-example.js).
108+
109+Definitions are also checked:
104110
105111[alpha]: #alpha
106112[charlie]: #charlie
113+
114+References w/o definitions are not checked: [delta]
107115```
108116
109117And our script, `example.js`, looks as follows:
@@ -116,7 +124,7 @@ var links = require('remark-validate-links')
116124
117125remark()
118126 .use(links)
119− .process(vfile.readSync('example.md'), function(err, file) {
127+ .process(vfile.readSync('example.md'), function (err, file) {
120128 console.error(report(err || file))
121129 })
122130```
@@ -125,25 +133,28 @@ Now, running `node example` yields:
125133
126134```markdown
127135example.md
128− 4:6-4:31 warning Link to unknown heading: `does-not` missing-heading remark-validate-links
129− 10:5-10:53 warning Link to unknown file: `missing-example.js` missing-file remark-validate-links
130− 13:1-13:20 warning Link to unknown heading: `charlie` missing-heading remark-validate-links
136+ 6:6-6:31 warning Link to unknown heading: `does-not` missing-heading remark-validate-links
137+ 11:5-11:53 warning Link to unknown file: `missing-example.js` missing-file remark-validate-links
138+ 16:1-16:20 warning Link to unknown heading: `charlie` missing-heading remark-validate-links
131139
132140⚠ 3 warnings
133141```
134142
143+(Note that `readme.md#nosuchheading` is not warned about, because the API
144+does not check headings in other Markdown files).
145+
135146## Configuration
136147
137148Typically, you don’t need to configure `remark-validate-links`, as it detects
138149local Git repositories.
139−If one is detected that references a known Git host, some extra links can be
140−checked.
150+If one is detected that references a known Git host (GitHub, GitLab,
151+or Bitbucket), some extra links can be checked.
141152If one is detected that does not reference a known Git host, local links still
142153work as expected.
143154If you’re not in a Git repository, you must pass `repository: false` explicitly.
144155
145156You can pass a `repository` (`string?`, `false`).
146−If `repository` is nully, the Git origin remote is detected.
157+If `repository` is nullish, the Git origin remote is detected.
147158If the repository resolves to something [npm understands][package-repository]
148159as a Git host such as GitHub, GitLab, or Bitbucket, full URLs to that host
149160(say, `https://github.com/remarkjs/remark-validate-links/readme.md#install`)
@@ -155,7 +166,7 @@ remark --use 'validate-links=repository:"foo/bar"' example.md
155166
156167For this to work, a `root` (`string?`) is also used, referencing the local Git
157168root directory (the place where `.git` is).
158−If both `root` and `repository` are nully, the Git root is detected.
169+If both `root` and `repository` are nullish, the Git root is detected.
159170If `root` is not given but `repository` is, [`file.cwd`][cwd] is used.
160171
161172You can define this repository in [configuration files][cli] too.
@@ -215,6 +226,15 @@ on nodes:
215226* `node.data.id` — Used, in the future, by other tools to signal
216227 unique identifiers on nodes
217228
229+## Security
230+
231+`remark-validate-links`, in Node, accesses the file system based on user
232+content, and this may be dangerous.
233+In Node `git remote` and `git rev-parse` also runs for processed files.
234+
235+The tree is not modified, so there are no openings for
236+[cross-site scripting (XSS)][xss] attacks.
237+
218238## Related
219239
220240* [`remark-lint`][remark-lint] — Markdown code style linter
@@ -226,8 +246,8 @@ See [`contributing.md`][contributing] in [`remarkjs/.github`][health] for ways
226246to get started.
227247See [`support.md`][support] for ways to get help.
228248
229−This project has a [Code of Conduct][coc].
230−By interacting with this repository, organisation, or community you agree to
249+This project has a [code of conduct][coc].
250+By interacting with this repository, organization, or community you agree to
231251abide by its terms.
232252
233253## License
@@ -236,7 +256,7 @@ abide by its terms.
236256
237257<!-- Definitions -->
238258
239−[build-badge]: https://img.shields.io/travis/remarkjs/remark-validate-links/master.svg
259+[build-badge]: https://img.shields.io/travis/remarkjs/remark-validate-links/main.svg
240260
241261[build]: https://travis-ci.org/remarkjs/remark-validate-links
242262
@@ -258,19 +278,19 @@ abide by its terms.
258278
259279[collective]: https://opencollective.com/unified
260280
261−[chat-badge]: https://img.shields.io/badge/join%20the%20community-on%20spectrum-7b16ff.svg
281+[chat-badge]: https://img.shields.io/badge/chat-discussions-success.svg
262282
263−[chat]: https://spectrum.chat/unified/remark
283+[chat]: https://github.com/remarkjs/remark/discussions
264284
265285[npm]: https://docs.npmjs.com/cli/install
266286
267287[health]: https://github.com/remarkjs/.github
268288
269−[contributing]: https://github.com/remarkjs/.github/blob/master/contributing.md
289+[contributing]: https://github.com/remarkjs/.github/blob/HEAD/contributing.md
270290
271−[support]: https://github.com/remarkjs/.github/blob/master/support.md
291+[support]: https://github.com/remarkjs/.github/blob/HEAD/support.md
272292
273−[coc]: https://github.com/remarkjs/.github/blob/master/code-of-conduct.md
293+[coc]: https://github.com/remarkjs/.github/blob/HEAD/code-of-conduct.md
274294
275295[license]: license
276296
@@ -278,7 +298,7 @@ abide by its terms.
278298
279299[remark]: https://github.com/remarkjs/remark
280300
281−[cli]: https://github.com/remarkjs/remark/tree/master/packages/remark-cli#readme
301+[cli]: https://github.com/remarkjs/remark/tree/HEAD/packages/remark-cli#readme
282302
283303[remark-lint]: https://github.com/remarkjs/remark-lint
284304
@@ -286,6 +306,10 @@ abide by its terms.
286306
287307[no-dead-urls]: https://github.com/davidtheclark/remark-lint-no-dead-urls
288308
309+[no-undef-refs]: https://github.com/remarkjs/remark-lint/tree/master/packages/remark-lint-no-undefined-references
310+
289311[package-repository]: https://docs.npmjs.com/files/package.json#repository
290312
291313[cwd]: https://github.com/vfile/vfile#vfilecwd
314+
315+[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting
test/fixtures/bitbucket.md+5−5
@@ -8,7 +8,7 @@ This is an ignored hash [link](#world).
88
99## Files
1010
11−This is a valid relative file [link](https://bitbucket.org/wooorm/test/src/master/examples/bitbucket.md).
11+This is a valid relative file [link](https://bitbucket.org/wooorm/test/src/main/examples/bitbucket.md).
1212
1313So is this [link](https://bitbucket.org/wooorm/test/src/foo-bar/examples/bitbucket.md).
1414
@@ -18,7 +18,7 @@ And this [link](examples/bitbucket.md).
1818
1919This is a valid external [file](../index.js).
2020
21−This is an invalid relative file [link](https://bitbucket.org/wooorm/test/src/master/examples/world.md).
21+This is an invalid relative file [link](https://bitbucket.org/wooorm/test/src/main/examples/world.md).
2222
2323So is this [link](https://bitbucket.org/wooorm/test/src/foo-bar/examples/world.md).
2424
@@ -32,7 +32,7 @@ Valid: [a](./examples/bitbucket.md#markdown-header-hello).
3232
3333Valid: [b](examples/bitbucket.md#markdown-header-hello).
3434
35−Valid: [c](https://bitbucket.org/wooorm/test/src/master/examples/bitbucket.md#markdown-header-hello).
35+Valid: [c](https://bitbucket.org/wooorm/test/src/main/examples/bitbucket.md#markdown-header-hello).
3636
3737Valid: [d](https://bitbucket.org/wooorm/test/src/foo-bar/examples/bitbucket.md#markdown-header-hello).
3838
@@ -40,7 +40,7 @@ Invalid: [e](./examples/bitbucket.md#markdown-header-world).
4040
4141Invalid: [f](examples/bitbucket.md#markdown-header-world).
4242
43−Invalid: [g](https://bitbucket.org/wooorm/test/src/master/examples/bitbucket.md#markdown-header-world).
43+Invalid: [g](https://bitbucket.org/wooorm/test/src/main/examples/bitbucket.md#markdown-header-world).
4444
4545Invalid: [h](https://bitbucket.org/wooorm/test/src/foo-bar/examples/bitbucket.md#markdown-header-world).
4646
@@ -48,7 +48,7 @@ Invalid: [i](./examples/world.md#markdown-header-hello).
4848
4949Invalid: [j](examples/world.md#markdown-header-hello).
5050
51−Invalid: [k](https://bitbucket.org/wooorm/test/src/master/examples/world.md#markdown-header-hello).
51+Invalid: [k](https://bitbucket.org/wooorm/test/src/main/examples/world.md#markdown-header-hello).
5252
5353Invalid: [l](https://bitbucket.org/wooorm/test/src/foo-bar/examples/world.md#markdown-header-hello).
5454
test/fixtures/examples/bitbucket.md+5−5
@@ -6,13 +6,13 @@ This is an invalid relative heading [link](#markdown-header-world).
66
77## Files
88
9−This is a valid relative file [link](https://bitbucket.org/wooorm/test/src/master/bitbucket.md).
9+This is a valid relative file [link](https://bitbucket.org/wooorm/test/src/main/bitbucket.md).
1010
1111So is this [link](https://bitbucket.org/wooorm/test/src/foo-bar/bitbucket.md).
1212
1313And this [link](../bitbucket.md).
1414
15−This is an invalid relative file [link](https://bitbucket.org/wooorm/test/src/master/world.md).
15+This is an invalid relative file [link](https://bitbucket.org/wooorm/test/src/main/world.md).
1616
1717So is this [link](https://bitbucket.org/wooorm/test/src/foo-bar/world.md).
1818
@@ -22,18 +22,18 @@ And this [link](../world.md).
2222
2323Valid: [a](../bitbucket.md#markdown-header-hello).
2424
25−Valid: [b](https://bitbucket.org/wooorm/test/src/master/bitbucket.md#markdown-header-hello).
25+Valid: [b](https://bitbucket.org/wooorm/test/src/main/bitbucket.md#markdown-header-hello).
2626
2727Valid: [c](https://bitbucket.org/wooorm/test/src/foo-bar/bitbucket.md#markdown-header-hello).
2828
2929Invalid: [d](../bitbucket.md#markdown-header-world).
3030
31−Invalid: [e](https://bitbucket.org/wooorm/test/src/master/bitbucket.md#markdown-header-world).
31+Invalid: [e](https://bitbucket.org/wooorm/test/src/main/bitbucket.md#markdown-header-world).
3232
3333Invalid: [f](https://bitbucket.org/wooorm/test/src/foo-bar/bitbucket.md#markdown-header-world).
3434
3535Invalid: [g](../world.md#markdown-header-hello).
3636
37−Invalid: [h](https://bitbucket.org/wooorm/test/src/master/world.md#markdown-header-hello).
37+Invalid: [h](https://bitbucket.org/wooorm/test/src/main/world.md#markdown-header-hello).
3838
3939Invalid: [i](https://bitbucket.org/wooorm/test/src/foo-bar/world.md#markdown-header-hello).
test/fixtures/examples/github.md+5−5
@@ -6,13 +6,13 @@ This is an invalid relative heading [link](#world).
66
77## Files
88
9−This is a valid relative file [link](https://github.com/wooorm/test/blob/master/github.md).
9+This is a valid relative file [link](https://github.com/wooorm/test/blob/main/github.md).
1010
1111So is this [link](https://github.com/wooorm/test/blob/foo-bar/github.md).
1212
1313And this [link](../github.md).
1414
15−This is an invalid relative file [link](https://github.com/wooorm/test/blob/master/world.md).
15+This is an invalid relative file [link](https://github.com/wooorm/test/blob/main/world.md).
1616
1717So is this [link](https://github.com/wooorm/test/blob/foo-bar/world.md).
1818
@@ -22,18 +22,18 @@ And this [link](../world.md).
2222
2323Valid: [a](../github.md#hello).
2424
25−Valid: [b](https://github.com/wooorm/test/blob/master/github.md#hello).
25+Valid: [b](https://github.com/wooorm/test/blob/main/github.md#hello).
2626
2727Valid: [c](https://github.com/wooorm/test/blob/foo-bar/github.md#hello).
2828
2929Invalid: [d](../github.md#world).
3030
31−Invalid: [e](https://github.com/wooorm/test/blob/master/github.md#world).
31+Invalid: [e](https://github.com/wooorm/test/blob/main/github.md#world).
3232
3333Invalid: [f](https://github.com/wooorm/test/blob/foo-bar/github.md#world).
3434
3535Invalid: [g](../world.md#hello).
3636
37−Invalid: [h](https://github.com/wooorm/test/blob/master/world.md#hello).
37+Invalid: [h](https://github.com/wooorm/test/blob/main/world.md#hello).
3838
3939Invalid: [i](https://github.com/wooorm/test/blob/foo-bar/world.md#hello).
test/fixtures/examples/gitlab.md+5−5
@@ -6,13 +6,13 @@ This is an invalid relative heading [link](#world).
66
77## Files
88
9−This is a valid relative file [link](https://gitlab.com/wooorm/test/blob/master/gitlab.md).
9+This is a valid relative file [link](https://gitlab.com/wooorm/test/blob/main/gitlab.md).
1010
1111So is this [link](https://gitlab.com/wooorm/test/blob/foo-bar/gitlab.md).
1212
1313And this [link](../gitlab.md).
1414
15−This is an invalid relative file [link](https://gitlab.com/wooorm/test/blob/master/world.md).
15+This is an invalid relative file [link](https://gitlab.com/wooorm/test/blob/main/world.md).
1616
1717So is this [link](https://gitlab.com/wooorm/test/blob/foo-bar/world.md).
1818
@@ -22,18 +22,18 @@ And this [link](../world.md).
2222
2323Valid: [a](../gitlab.md#hello).
2424
25−Valid: [b](https://gitlab.com/wooorm/test/blob/master/gitlab.md#hello).
25+Valid: [b](https://gitlab.com/wooorm/test/blob/main/gitlab.md#hello).
2626
2727Valid: [c](https://gitlab.com/wooorm/test/blob/foo-bar/gitlab.md#hello).
2828
2929Invalid: [d](../gitlab.md#world).
3030
31−Invalid: [e](https://gitlab.com/wooorm/test/blob/master/gitlab.md#world).
31+Invalid: [e](https://gitlab.com/wooorm/test/blob/main/gitlab.md#world).
3232
3333Invalid: [f](https://gitlab.com/wooorm/test/blob/foo-bar/gitlab.md#world).
3434
3535Invalid: [g](../world.md#hello).
3636
37−Invalid: [h](https://gitlab.com/wooorm/test/blob/master/world.md#hello).
37+Invalid: [h](https://gitlab.com/wooorm/test/blob/main/world.md#hello).
3838
3939Invalid: [i](https://gitlab.com/wooorm/test/blob/foo-bar/world.md#hello).
test/fixtures/file-as-folder.mdnew file+1
@@ -0,0 +1 @@
1+[](file-as-folder.md/other)
test/fixtures/folder-without-readme/example.mdnew file+1
@@ -0,0 +1 @@
1+This file isn’t used when linking to the folder: it has to be a `readme`.
test/fixtures/folder.mdnew file+23
@@ -0,0 +1,23 @@
1+Here we link to a folder:
2+
3+Explicit:
4+
5+[OK](./folder/readme.markdown#this)
6+
7+[OK](./folder/readme.markdown#that)
8+
9+[NOK](./folder/readme.markdown#missing)
10+
11+Implicit:
12+
13+[OK](./folder#this)
14+
15+[OK](./folder#that)
16+
17+[NOK](./folder#missing)
18+
19+Other:
20+
21+[NOK](./missing#missing)
22+
23+[NOK](./folder-without-readme#missing)
test/fixtures/folder/example.mdnew file+1
@@ -0,0 +1 @@
1+This file isn’t used when linking to the folder: it has to be a `readme`.
test/fixtures/folder/readme.ascnew file+9
@@ -0,0 +1,9 @@
1+readme
2+------
3+
4+While GitHub would pick up on this readme for the folder,
5+`remark-validate-links` is for Markdown, so we ignore AsciiDoc.
6+
7+== This
8+
9+== That
test/fixtures/folder/readme.markdownnew file+5
@@ -0,0 +1,5 @@
1+# readme
2+
3+## This
4+
5+## That
test/fixtures/folder/readme.mdnew file+1
@@ -0,0 +1 @@
1+This one isn’t used (`readme.markdown` sorts before `readme.md`).
test/fixtures/github.md+11−7
@@ -6,9 +6,9 @@ This is an invalid relative heading [link](#world).
66
77## Files
88
9−This is a valid relative file [link](https://github.com/wooorm/test/blob/master/examples/github.md).
9+This is a valid relative file [link](https://github.com/wooorm/test/blob/main/examples/github.md).
1010
11−This is a valid absolute file [link](/wooorm/test/blob/master/examples/github.md).
11+This is a valid absolute file [link](/wooorm/test/blob/main/examples/github.md).
1212
1313So is this [link](https://github.com/wooorm/test/blob/foo-bar/examples/github.md).
1414
@@ -18,9 +18,9 @@ And this [link](examples/github.md).
1818
1919This is a valid external [file](../index.js).
2020
21−This is an invalid relative file [link](https://github.com/wooorm/test/blob/master/examples/world.md).
21+This is an invalid relative file [link](https://github.com/wooorm/test/blob/main/examples/world.md).
2222
23−This is an invalid absolute file [link](/wooorm/test/blob/master/examples/world.md).
23+This is an invalid absolute file [link](/wooorm/test/blob/main/examples/world.md).
2424
2525So is this [link](https://github.com/wooorm/test/blob/foo-bar/examples/world.md).
2626
@@ -34,7 +34,7 @@ Valid: [a](./examples/github.md#hello).
3434
3535Valid: [b](examples/github.md#hello).
3636
37−Valid: [c](https://github.com/wooorm/test/blob/master/examples/github.md#hello).
37+Valid: [c](https://github.com/wooorm/test/blob/main/examples/github.md#hello).
3838
3939Valid: [d](https://github.com/wooorm/test/blob/foo-bar/examples/github.md#hello).
4040
@@ -42,7 +42,7 @@ Invalid: [e](./examples/github.md#world).
4242
4343Invalid: [f](examples/github.md#world).
4444
45−Invalid: [g](https://github.com/wooorm/test/blob/master/examples/github.md#world).
45+Invalid: [g](https://github.com/wooorm/test/blob/main/examples/github.md#world).
4646
4747Invalid: [h](https://github.com/wooorm/test/blob/foo-bar/examples/github.md#world).
4848
@@ -50,7 +50,7 @@ Invalid: [i](./examples/world.md#hello).
5050
5151Invalid: [j](examples/world.md#hello).
5252
53−Invalid: [k](https://github.com/wooorm/test/blob/master/examples/world.md#hello).
53+Invalid: [k](https://github.com/wooorm/test/blob/main/examples/world.md#hello).
5454
5555Invalid: [l](https://github.com/wooorm/test/blob/foo-bar/examples/world.md#hello).
5656
@@ -65,3 +65,7 @@ Valid: [b](http://example.com).
6565Valid: [b](http://example.com/foo/bar/baz).
6666
6767Valid: [b](http://bitbucket.com/wooorm/test/blob/foo-bar/examples/world.md#hello).
68+
69+## Top Anchor
70+
71+This links to the start of the document [link](#readme).
test/fixtures/gitlab.md+9−5
@@ -6,7 +6,7 @@ This is an invalid relative heading [link](#world).
66
77## Files
88
9−This is a valid relative file [link](https://gitlab.com/wooorm/test/blob/master/examples/gitlab.md).
9+This is a valid relative file [link](https://gitlab.com/wooorm/test/blob/main/examples/gitlab.md).
1010
1111So is this [link](https://gitlab.com/wooorm/test/blob/foo-bar/examples/gitlab.md).
1212
@@ -16,7 +16,7 @@ And this [link](examples/gitlab.md).
1616
1717This is a valid external [file](../index.js).
1818
19−This is an invalid relative file [link](https://gitlab.com/wooorm/test/blob/master/examples/world.md).
19+This is an invalid relative file [link](https://gitlab.com/wooorm/test/blob/main/examples/world.md).
2020
2121So is this [link](https://gitlab.com/wooorm/test/blob/foo-bar/examples/world.md).
2222
@@ -30,7 +30,7 @@ Valid: [a](./examples/gitlab.md#hello).
3030
3131Valid: [b](examples/gitlab.md#hello).
3232
33−Valid: [c](https://gitlab.com/wooorm/test/blob/master/examples/gitlab.md#hello).
33+Valid: [c](https://gitlab.com/wooorm/test/blob/main/examples/gitlab.md#hello).
3434
3535Valid: [d](https://gitlab.com/wooorm/test/blob/foo-bar/examples/gitlab.md#hello).
3636
@@ -38,7 +38,7 @@ Invalid: [e](./examples/gitlab.md#world).
3838
3939Invalid: [f](examples/gitlab.md#world).
4040
41−Invalid: [g](https://gitlab.com/wooorm/test/blob/master/examples/gitlab.md#world).
41+Invalid: [g](https://gitlab.com/wooorm/test/blob/main/examples/gitlab.md#world).
4242
4343Invalid: [h](https://gitlab.com/wooorm/test/blob/foo-bar/examples/gitlab.md#world).
4444
@@ -46,7 +46,7 @@ Invalid: [i](./examples/world.md#hello).
4646
4747Invalid: [j](examples/world.md#hello).
4848
49−Invalid: [k](https://gitlab.com/wooorm/test/blob/master/examples/world.md#hello).
49+Invalid: [k](https://gitlab.com/wooorm/test/blob/main/examples/world.md#hello).
5050
5151Invalid: [l](https://gitlab.com/wooorm/test/blob/foo-bar/examples/world.md#hello).
5252
@@ -61,3 +61,7 @@ Valid: [b](http://example.com).
6161Valid: [b](http://example.com/foo/bar/baz).
6262
6363Valid: [b](http://bitbucket.com/wooorm/test/blob/foo-bar/examples/world.md#hello).
64+
65+## Top Anchor
66+
67+This links to the start of the document [link](#readme).
test/fixtures/images.md+4−4
@@ -6,7 +6,7 @@ Relative ![image](./examples/image.jpg)
66
77No `./` in ![image](examples/image.jpg)
88
9−Absolute ![image](https://github.com/wooorm/test/blob/master/examples/image.jpg)
9+Absolute ![image](https://github.com/wooorm/test/blob/main/examples/image.jpg)
1010
1111Relative ![image reference][rel]
1212
@@ -20,7 +20,7 @@ Relative ![missing image](./examples/missing.jpg)
2020
2121No `./` in ![image](examples/missing.jpg)
2222
23−Absolute ![missing image](https://github.com/wooorm/test/blob/master/examples/missing.jpg)
23+Absolute ![missing image](https://github.com/wooorm/test/blob/main/examples/missing.jpg)
2424
2525Relative ![missing image reference][rel-missing]
2626
@@ -30,10 +30,10 @@ Absolute ![missing image reference][abs-missing]
3030
3131[rel]: ./examples/image.jpg
3232
33−[abs]: https://github.com/wooorm/test/blob/master/examples/image.jpg
33+[abs]: https://github.com/wooorm/test/blob/main/examples/image.jpg
3434
3535[rel-missing]: ./examples/missing.jpg
3636
37−[abs-missing]: https://github.com/wooorm/test/blob/master/examples/missing.jpg
37+[abs-missing]: https://github.com/wooorm/test/blob/main/examples/missing.jpg
3838
3939[rel-whitespace]: "./examples/image with space.jpg"
test/fixtures/line-links.md+2−2
@@ -4,6 +4,6 @@ Link to [a line](./examples/example.js#L1)
44
55Link to [a line in a missing file](./examples/missing.js#L1)
66
7−[a](https://github.com/wooorm/test/blob/master/examples/example.js#L1).
7+[a](https://github.com/wooorm/test/blob/main/examples/example.js#L1).
88
9−[b](https://github.com/wooorm/test/blob/master/examples/missing.js#L1).
9+[b](https://github.com/wooorm/test/blob/main/examples/missing.js#L1).
test/fixtures/self-hosted.md+2−2
@@ -1,5 +1,5 @@
11# Hello
22
3−[Fine](https://gitlab.acme.com/acme/project/blob/master/self-hosted.md#hello);
3+[Fine](https://gitlab.acme.com/acme/project/blob/main/self-hosted.md#hello);
44
5−[Not fine](https://gitlab.acme.com/acme/project/blob/master/self-hosted.md#world);
5+[Not fine](https://gitlab.acme.com/acme/project/blob/main/self-hosted.md#world);
test/index.js+1019−769
@@ -2,8 +2,8 @@
22
33var fs = require('fs')
44var path = require('path')
5+var childProcess = require('child_process')
56var test = require('tape')
6−var execa = require('execa')
77var vfile = require('to-vfile')
88var remark = require('remark')
99var strip = require('strip-ansi')
@@ -13,20 +13,20 @@ var links = require('..')
1313
1414process.chdir(path.resolve(process.cwd(), 'test', 'fixtures'))
1515
16−test.onFinish(function() {
16+test.onFinish(function () {
1717 process.chdir(path.resolve(process.cwd(), '..', '..'))
1818})
1919
2020var bin = path.join('..', '..', 'node_modules', '.bin', 'remark')
2121
22−test('remark-validate-links', function(t) {
23− t.test('should work on the API', function(st) {
22+test('remark-validate-links', function (t) {
23+ t.test('should work on the API', function (st) {
2424 st.plan(1)
2525
2626 remark()
2727 .use(links)
2828 .use(sort)
29− .process(vfile.readSync('github.md'), function(err, file) {
29+ .process(vfile.readSync('github.md'), function (err, file) {
3030 st.deepEqual(
3131 [err].concat(file.messages.map(String)),
3232 [
@@ -42,116 +42,134 @@ test('remark-validate-links', function(t) {
4242 })
4343 })
4444
45− t.test('should ignore invalid repositories', function(st) {
45+ t.test('should ignore invalid repositories', function (st) {
4646 st.plan(1)
4747
48− execa(bin, [
49− '--no-config',
50− '--no-ignore',
51− '--use',
52− '../..=repository:"invalid:shortcode"',
53− '--use',
54− '../sort',
55− 'small.md'
56− ]).then(
57− function(result) {
58− st.equal(
59− strip(result.stderr),
48+ childProcess.exec(
49+ [
50+ bin,
51+ '--no-config',
52+ '--no-ignore',
53+ '--use',
54+ '"../..=repository:\\"invalid:shortcode\\""',
55+ '--use',
56+ '../sort',
57+ 'small.md'
58+ ].join(' '),
59+ onexec
60+ )
61+
62+ function onexec(err, stdout, stderr) {
63+ st.deepEqual(
64+ [err, strip(stderr)],
65+ [
66+ null,
6067 [
6168 'small.md',
6269 ' 5:13-5:27 warning Link to unknown heading: `world` missing-heading remark-validate-links',
6370 '',
64− '⚠ 1 warning'
65− ].join('\n'),
66− 'should work'
67− )
68− },
69− function(err) {
70− st.error(err)
71− }
72− )
71+ '⚠ 1 warning',
72+ ''
73+ ].join('\n')
74+ ],
75+ 'should work'
76+ )
77+ }
7378 })
7479
75− t.test('should throw on Gist repositories', function(st) {
80+ t.test('should throw on Gist repositories', function (st) {
7681 st.plan(1)
7782
78− execa(bin, [
79− '--no-config',
80− '--no-ignore',
81− '--use',
82− '../..=repository:"gist:wooorm/8504606"',
83− '--use',
84− '../sort',
85− 'small.md'
86− ]).then(
87− function(result) {
88− st.equal(
89− strip(result.stderr),
83+ childProcess.exec(
84+ [
85+ bin,
86+ '--no-config',
87+ '--no-ignore',
88+ '--use',
89+ '"../..=repository:\\"gist:wooorm/8504606\\""',
90+ '--use',
91+ '../sort',
92+ 'small.md'
93+ ].join(' '),
94+ onexec
95+ )
96+
97+ function onexec(err, stdout, stderr) {
98+ st.deepEqual(
99+ [err, strip(stderr)],
100+ [
101+ null,
90102 [
91103 'small.md',
92104 ' 5:13-5:27 warning Link to unknown heading: `world` missing-heading remark-validate-links',
93105 '',
94− '⚠ 1 warning'
95− ].join('\n'),
96− 'should work'
97− )
98− },
99− function(err) {
100− st.error(err, 'should not fail')
101− }
102− )
106+ '⚠ 1 warning',
107+ ''
108+ ].join('\n')
109+ ],
110+ 'should work'
111+ )
112+ }
103113 })
104114
105− t.test('should ignore unfound files (#1)', function(st) {
115+ t.test('should ignore unfound files (#1)', function (st) {
106116 st.plan(1)
107117
108− execa(bin, [
109− '--no-config',
110− '--no-ignore',
111− '--use',
112− '../..',
113− '--use',
114− '../sort',
115− 'FOOOO'
116− ]).then(
117− function() {
118− st.fail('should not be successful')
119− },
120− function(err) {
121− st.equal(
122− strip(err.stderr),
118+ childProcess.exec(
119+ [
120+ bin,
121+ '--no-config',
122+ '--no-ignore',
123+ '--use',
124+ '../..',
125+ '--use',
126+ '../sort',
127+ 'FOOOO'
128+ ].join(' '),
129+ onexec
130+ )
131+
132+ function onexec(err, stdout, stderr) {
133+ st.deepEqual(
134+ [/command failed/i.test(err), strip(stderr)],
135+ [
136+ true,
123137 [
124138 'FOOOO',
125139 ' 1:1 error No such file or directory',
126140 '',
127141 '✖ 1 error',
128142 ''
129− ].join('\n'),
130− 'should report an error'
131− )
132− }
133− )
143+ ].join('\n')
144+ ],
145+ 'should work'
146+ )
147+ }
134148 })
135149
136− t.test('should ignore unfound files (#2)', function(st) {
150+ t.test('should ignore unfound files (#2)', function (st) {
137151 st.plan(1)
138152
139− execa(bin, [
140− '--no-config',
141− '--no-ignore',
142− '--use',
143− '../..',
144− '--use',
145− '../sort',
146− 'definitions.md',
147− 'FOOOO'
148− ]).then(
149− function() {
150− st.fail('should not be successful')
151− },
152− function(err) {
153− st.equal(
154− strip(err.stderr),
153+ childProcess.exec(
154+ [
155+ bin,
156+ '--no-config',
157+ '--no-ignore',
158+ '--use',
159+ '../..',
160+ '--use',
161+ '../sort',
162+ 'definitions.md',
163+ 'FOOOO'
164+ ].join(' '),
165+ onexec
166+ )
167+
168+ function onexec(err, stdout, stderr) {
169+ st.deepEqual(
170+ [/command failed/i.test(err), strip(stderr)],
171+ [
172+ true,
155173 [
156174 'FOOOO',
157175 ' 1:1 error No such file or directory',
@@ -161,492 +179,555 @@ test('remark-validate-links', function(t) {
161179 '',
162180 '2 messages (✖ 1 error, ⚠ 1 warning)',
163181 ''
164− ].join('\n'),
165− 'should report an error'
166− )
167− }
168− )
182+ ].join('\n')
183+ ],
184+ 'should work'
185+ )
186+ }
169187 })
170188
171− t.test('should work if there are no links', function(st) {
189+ t.test('should work if there are no links', function (st) {
172190 st.plan(1)
173191
174− execa(bin, [
175− '--no-config',
176− '--no-ignore',
177− '--use',
178− '../..',
179− '--use',
180− '../sort',
181− 'empty.md'
182− ]).then(function(result) {
183− st.equal(
184− strip(result.stderr),
185− 'empty.md: no issues found',
186− 'should report'
192+ childProcess.exec(
193+ [
194+ bin,
195+ '--no-config',
196+ '--no-ignore',
197+ '--use',
198+ '../..',
199+ '--use',
200+ '../sort',
201+ 'empty.md'
202+ ].join(' '),
203+ onexec
204+ )
205+
206+ function onexec(err, stdout, stderr) {
207+ st.deepEqual(
208+ [err, strip(stderr)],
209+ [null, 'empty.md: no issues found\n'],
210+ 'should work'
187211 )
188− }, st.error)
212+ }
189213 })
190214
191− t.test('should work with stdin', function(st) {
215+ t.test('should work with stdin', function (st) {
192216 st.plan(1)
193217
194− var subprocess = execa(bin, [
195− '--no-config',
196− '--no-ignore',
197− '--use',
198− '../..',
199− '--use',
200− '../sort'
201− ])
218+ var subprocess = childProcess.exec(
219+ [
220+ bin,
221+ '--no-config',
222+ '--no-ignore',
223+ '--use',
224+ '../..',
225+ '--use',
226+ '../sort'
227+ ].join(' '),
228+ onexec
229+ )
202230
203231 fs.createReadStream('github.md').pipe(subprocess.stdin)
204232
205− subprocess.then(function(result) {
206− st.equal(
207− strip(result.stderr),
233+ function onexec(err, stdout, stderr) {
234+ st.deepEqual(
235+ [err, strip(stderr)],
208236 [
209− '<stdin>',
210− ' 5:37-5:51 warning Link to unknown heading: `world` missing-heading remark-validate-links',
211− '',
212− '⚠ 1 warning'
213− ].join('\n'),
214− 'should report an error'
237+ null,
238+ [
239+ '<stdin>',
240+ ' 5:37-5:51 warning Link to unknown heading: `world` missing-heading remark-validate-links',
241+ '',
242+ '⚠ 1 warning',
243+ ''
244+ ].join('\n')
245+ ],
246+ 'should work'
215247 )
216− }, st.error)
248+ }
217249 })
218250
219− t.test('should work when not all files are given', function(st) {
251+ t.test('should work when not all files are given', function (st) {
220252 st.plan(1)
221253
222− execa(bin, [
223− '--no-config',
224− '--no-ignore',
225− '--use',
226− '../..',
227− '--use',
228− '../sort',
229− 'github.md'
230− ]).then(function(result) {
231− st.equal(
232− strip(result.stderr),
254+ childProcess.exec(
255+ [
256+ bin,
257+ '--no-config',
258+ '--no-ignore',
259+ '--use',
260+ '../..',
261+ '--use',
262+ '../sort',
263+ 'github.md'
264+ ].join(' '),
265+ onexec
266+ )
267+
268+ function onexec(err, stdout, stderr) {
269+ st.deepEqual(
270+ [err, strip(stderr)],
233271 [
234− 'github.md',
235− ' 5:37-5:51 warning Link to unknown heading: `world` missing-heading remark-validate-links',
236− ' 27:10-27:37 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
237− ' 29:10-29:35 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
238− ' 41:10-41:41 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
239− ' 43:10-43:39 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
240− ' 49:10-49:40 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
241− ' 49:10-49:40 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
242− ' 51:10-51:38 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
243− ' 51:10-51:38 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
244− '',
245− '⚠ 9 warnings'
246− ].join('\n'),
247− 'should report'
272+ null,
273+ [
274+ 'github.md',
275+ ' 5:37-5:51 warning Link to unknown heading: `world` missing-heading remark-validate-links',
276+ ' 27:10-27:37 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
277+ ' 29:10-29:35 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
278+ ' 41:10-41:41 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
279+ ' 43:10-43:39 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
280+ ' 49:10-49:40 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
281+ ' 49:10-49:40 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
282+ ' 51:10-51:38 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
283+ ' 51:10-51:38 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
284+ '',
285+ '⚠ 9 warnings',
286+ ''
287+ ].join('\n')
288+ ],
289+ 'should work'
248290 )
249− }, st.error)
291+ }
250292 })
251293
252− t.test('should work when all files are given', function(st) {
294+ t.test('should work when all files are given', function (st) {
253295 st.plan(1)
254296
255− execa(bin, [
256− '--no-config',
257− '--no-ignore',
258− '--use',
259− '../..',
260− '--use',
261− '../sort',
262− 'github.md',
263− 'examples/github.md'
264− ]).then(function(result) {
265− st.equal(
266− strip(result.stderr),
297+ childProcess.exec(
298+ [
299+ bin,
300+ '--no-config',
301+ '--no-ignore',
302+ '--use',
303+ '../..',
304+ '--use',
305+ '../sort',
306+ 'github.md',
307+ 'examples/github.md'
308+ ].join(' '),
309+ onexec
310+ )
311+
312+ function onexec(err, stdout, stderr) {
313+ st.deepEqual(
314+ [err, strip(stderr)],
267315 [
268− 'examples/github.md',
269− ' 5:37-5:51 warning Link to unknown heading: `world` missing-heading remark-validate-links',
270− ' 19:10-19:29 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
271− ' 29:10-29:33 warning Link to unknown heading in `../github.md`: `world` missing-heading-in-file remark-validate-links',
272− ' 35:10-35:32 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
273− ' 35:10-35:32 warning Link to unknown heading in `../world.md`: `hello` missing-heading-in-file remark-validate-links',
274− '',
275− 'github.md',
276− ' 5:37-5:51 warning Link to unknown heading: `world` missing-heading remark-validate-links',
277− ' 27:10-27:37 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
278− ' 29:10-29:35 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
279− ' 41:10-41:41 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
280− ' 43:10-43:39 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
281− ' 49:10-49:40 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
282− ' 49:10-49:40 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
283− ' 51:10-51:38 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
284− ' 51:10-51:38 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
285− '',
286− '⚠ 14 warnings'
287− ].join('\n'),
288− 'should report'
316+ null,
317+ [
318+ 'examples/github.md',
319+ ' 5:37-5:51 warning Link to unknown heading: `world` missing-heading remark-validate-links',
320+ ' 19:10-19:29 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
321+ ' 29:10-29:33 warning Link to unknown heading in `../github.md`: `world` missing-heading-in-file remark-validate-links',
322+ ' 35:10-35:32 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
323+ ' 35:10-35:32 warning Link to unknown heading in `../world.md`: `hello` missing-heading-in-file remark-validate-links',
324+ '',
325+ 'github.md',
326+ ' 5:37-5:51 warning Link to unknown heading: `world` missing-heading remark-validate-links',
327+ ' 27:10-27:37 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
328+ ' 29:10-29:35 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
329+ ' 41:10-41:41 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
330+ ' 43:10-43:39 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
331+ ' 49:10-49:40 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
332+ ' 49:10-49:40 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
333+ ' 51:10-51:38 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
334+ ' 51:10-51:38 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
335+ '',
336+ '⚠ 14 warnings',
337+ ''
338+ ].join('\n')
339+ ],
340+ 'should work'
289341 )
290− }, st.error)
342+ }
291343 })
292344
293− t.test('should work with definitions', function(st) {
345+ t.test('should work with definitions', function (st) {
294346 st.plan(1)
295347
296− execa(bin, [
297− '--no-config',
298− '--no-ignore',
299− '--use',
300− '../..',
301− '--use',
302− '../sort',
303− 'definitions.md'
304− ]).then(function(result) {
305− st.equal(
306− strip(result.stderr),
348+ childProcess.exec(
349+ [
350+ bin,
351+ '--no-config',
352+ '--no-ignore',
353+ '--use',
354+ '../..',
355+ '--use',
356+ '../sort',
357+ 'definitions.md'
358+ ].join(' '),
359+ onexec
360+ )
361+
362+ function onexec(err, stdout, stderr) {
363+ st.deepEqual(
364+ [err, strip(stderr)],
307365 [
308− 'definitions.md',
309− ' 10:1-10:18 warning Link to unknown heading: `world` missing-heading remark-validate-links',
310− '',
311− '⚠ 1 warning'
312− ].join('\n'),
313− 'should report'
366+ null,
367+ [
368+ 'definitions.md',
369+ ' 10:1-10:18 warning Link to unknown heading: `world` missing-heading remark-validate-links',
370+ '',
371+ '⚠ 1 warning',
372+ ''
373+ ].join('\n')
374+ ],
375+ 'should work'
314376 )
315− }, st.error)
377+ }
316378 })
317379
318− t.test('should work on GitHub URLs when given a repo', function(st) {
380+ t.test('should work on GitHub URLs when given a repo', function (st) {
319381 st.plan(1)
320382
321− execa(bin, [
322− '--no-config',
323− '--no-ignore',
324− '--use',
325− '../..=repository:"wooorm/test"',
326− '--use',
327− '../sort',
328− 'github.md',
329− 'examples/github.md'
330− ]).then(function(result) {
331− st.equal(
332− strip(result.stderr),
383+ childProcess.exec(
384+ [
385+ bin,
386+ '--no-config',
387+ '--no-ignore',
388+ '--use',
389+ '"../..=repository:\\"wooorm/test\\""',
390+ '--use',
391+ '../sort',
392+ 'github.md',
393+ 'examples/github.md'
394+ ].join(' '),
395+ onexec
396+ )
397+
398+ function onexec(err, stdout, stderr) {
399+ st.deepEqual(
400+ [err, strip(stderr)],
333401 [
334− 'examples/github.md',
335− ' 5:37-5:51 warning Link to unknown heading: `world` missing-heading remark-validate-links',
336− ' 15:34-15:93 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
337− ' 17:12-17:72 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
338− ' 19:10-19:29 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
339− ' 29:10-29:33 warning Link to unknown heading in `../github.md`: `world` missing-heading-in-file remark-validate-links',
340− ' 31:10-31:73 warning Link to unknown heading in `../github.md`: `world` missing-heading-in-file remark-validate-links',
341− ' 33:10-33:74 warning Link to unknown heading in `../github.md`: `world` missing-heading-in-file remark-validate-links',
342− ' 35:10-35:32 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
343− ' 35:10-35:32 warning Link to unknown heading in `../world.md`: `hello` missing-heading-in-file remark-validate-links',
344− ' 37:10-37:72 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
345− ' 37:10-37:72 warning Link to unknown heading in `../world.md`: `hello` missing-heading-in-file remark-validate-links',
346− ' 39:10-39:73 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
347− ' 39:10-39:73 warning Link to unknown heading in `../world.md`: `hello` missing-heading-in-file remark-validate-links',
348− '',
349− 'github.md',
350− ' 5:37-5:51 warning Link to unknown heading: `world` missing-heading remark-validate-links',
351− ' 21:34-21:102 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
352− ' 23:34-23:84 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
353− ' 25:12-25:81 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
354− ' 27:10-27:37 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
355− ' 29:10-29:35 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
356− ' 41:10-41:41 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
357− ' 43:10-43:39 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
358− ' 45:10-45:82 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
359− ' 47:10-47:83 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
360− ' 49:10-49:40 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
361− ' 49:10-49:40 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
362− ' 51:10-51:38 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
363− ' 51:10-51:38 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
364− ' 53:10-53:81 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
365− ' 53:10-53:81 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
366− ' 55:10-55:82 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
367− ' 55:10-55:82 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
368− '',
369− '⚠ 31 warnings'
370− ].join('\n'),
371− 'should report'
402+ null,
403+ [
404+ 'examples/github.md',
405+ ' 5:37-5:51 warning Link to unknown heading: `world` missing-heading remark-validate-links',
406+ ' 15:34-15:91 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
407+ ' 17:12-17:72 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
408+ ' 19:10-19:29 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
409+ ' 29:10-29:33 warning Link to unknown heading in `../github.md`: `world` missing-heading-in-file remark-validate-links',
410+ ' 31:10-31:71 warning Link to unknown heading in `../github.md`: `world` missing-heading-in-file remark-validate-links',
411+ ' 33:10-33:74 warning Link to unknown heading in `../github.md`: `world` missing-heading-in-file remark-validate-links',
412+ ' 35:10-35:32 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
413+ ' 35:10-35:32 warning Link to unknown heading in `../world.md`: `hello` missing-heading-in-file remark-validate-links',
414+ ' 37:10-37:70 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
415+ ' 37:10-37:70 warning Link to unknown heading in `../world.md`: `hello` missing-heading-in-file remark-validate-links',
416+ ' 39:10-39:73 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
417+ ' 39:10-39:73 warning Link to unknown heading in `../world.md`: `hello` missing-heading-in-file remark-validate-links',
418+ '',
419+ 'github.md',
420+ ' 5:37-5:51 warning Link to unknown heading: `world` missing-heading remark-validate-links',
421+ ' 21:34-21:100 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
422+ ' 23:34-23:82 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
423+ ' 25:12-25:81 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
424+ ' 27:10-27:37 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
425+ ' 29:10-29:35 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
426+ ' 41:10-41:41 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
427+ ' 43:10-43:39 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
428+ ' 45:10-45:80 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
429+ ' 47:10-47:83 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
430+ ' 49:10-49:40 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
431+ ' 49:10-49:40 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
432+ ' 51:10-51:38 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
433+ ' 51:10-51:38 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
434+ ' 53:10-53:79 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
435+ ' 53:10-53:79 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
436+ ' 55:10-55:82 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
437+ ' 55:10-55:82 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
438+ '',
439+ '⚠ 31 warnings',
440+ ''
441+ ].join('\n')
442+ ],
443+ 'should work'
372444 )
373− }, st.error)
445+ }
374446 })
375447
376− t.test('should work when with Git directory', function(st) {
448+ t.test('should work when with Git directory', function (st) {
377449 st.plan(1)
378450
379− Promise.resolve()
380− .then(function() {
381− return execa('git', ['init'])
382− })
383− .then(function() {
384− return execa('git', [
385− 'remote',
386− 'add',
387− 'origin',
388− 'git@github.com:wooorm/test.git'
389− ])
390− })
391− .then(function() {
392− return execa(bin, [
393− '--no-config',
394− '--no-ignore',
395− '--use',
396− '../..',
397− '--use',
398− '../sort',
399− 'github.md',
400− 'examples/github.md'
401− ])
402− })
403− .then(
404− function(result) {
405− clean()
406− st.equal(
407− strip(result.stderr),
408− [
409− 'examples/github.md',
410− ' 5:37-5:51 warning Link to unknown heading: `world` missing-heading remark-validate-links',
411− ' 15:34-15:93 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
412− ' 17:12-17:72 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
413− ' 19:10-19:29 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
414− ' 29:10-29:33 warning Link to unknown heading in `../github.md`: `world` missing-heading-in-file remark-validate-links',
415− ' 31:10-31:73 warning Link to unknown heading in `../github.md`: `world` missing-heading-in-file remark-validate-links',
416− ' 33:10-33:74 warning Link to unknown heading in `../github.md`: `world` missing-heading-in-file remark-validate-links',
417− ' 35:10-35:32 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
418− ' 35:10-35:32 warning Link to unknown heading in `../world.md`: `hello` missing-heading-in-file remark-validate-links',
419− ' 37:10-37:72 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
420− ' 37:10-37:72 warning Link to unknown heading in `../world.md`: `hello` missing-heading-in-file remark-validate-links',
421− ' 39:10-39:73 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
422− ' 39:10-39:73 warning Link to unknown heading in `../world.md`: `hello` missing-heading-in-file remark-validate-links',
423− '',
424− 'github.md',
425− ' 5:37-5:51 warning Link to unknown heading: `world` missing-heading remark-validate-links',
426− ' 21:34-21:102 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
427− ' 23:34-23:84 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
428− ' 25:12-25:81 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
429− ' 27:10-27:37 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
430− ' 29:10-29:35 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
431− ' 41:10-41:41 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
432− ' 43:10-43:39 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
433− ' 45:10-45:82 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
434− ' 47:10-47:83 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
435− ' 49:10-49:40 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
436− ' 49:10-49:40 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
437− ' 51:10-51:38 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
438− ' 51:10-51:38 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
439− ' 53:10-53:81 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
440− ' 53:10-53:81 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
441− ' 55:10-55:82 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
442− ' 55:10-55:82 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
443− '',
444− '⚠ 31 warnings'
445− ].join('\n'),
446− 'should report'
447− )
448− },
449− function(err) {
450− clean()
451− st.error(err)
452− }
451+ childProcess.exec('git init', oninit)
452+
453+ function oninit(err) {
454+ if (err) {
455+ t.ifErr(err)
456+ } else {
457+ childProcess.exec(
458+ 'git remote add origin git@github.com:wooorm/test.git',
459+ onremote
460+ )
461+ }
462+ }
463+
464+ function onremote(err) {
465+ if (err) {
466+ clean()
467+ t.ifErr(err)
468+ } else {
469+ childProcess.exec(
470+ [
471+ bin,
472+ '--no-config',
473+ '--no-ignore',
474+ '--use',
475+ '../..',
476+ '--use',
477+ '../sort',
478+ 'github.md',
479+ 'examples/github.md'
480+ ].join(' '),
481+ onexec
482+ )
483+ }
484+ }
485+
486+ function onexec(err, stdout, stderr) {
487+ clean()
488+ st.deepEqual(
489+ [err, strip(stderr)],
490+ [
491+ null,
492+ [
493+ 'examples/github.md',
494+ ' 5:37-5:51 warning Link to unknown heading: `world` missing-heading remark-validate-links',
495+ ' 15:34-15:91 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
496+ ' 17:12-17:72 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
497+ ' 19:10-19:29 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
498+ ' 29:10-29:33 warning Link to unknown heading in `../github.md`: `world` missing-heading-in-file remark-validate-links',
499+ ' 31:10-31:71 warning Link to unknown heading in `../github.md`: `world` missing-heading-in-file remark-validate-links',
500+ ' 33:10-33:74 warning Link to unknown heading in `../github.md`: `world` missing-heading-in-file remark-validate-links',
501+ ' 35:10-35:32 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
502+ ' 35:10-35:32 warning Link to unknown heading in `../world.md`: `hello` missing-heading-in-file remark-validate-links',
503+ ' 37:10-37:70 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
504+ ' 37:10-37:70 warning Link to unknown heading in `../world.md`: `hello` missing-heading-in-file remark-validate-links',
505+ ' 39:10-39:73 warning Link to unknown file: `../world.md` missing-file remark-validate-links',
506+ ' 39:10-39:73 warning Link to unknown heading in `../world.md`: `hello` missing-heading-in-file remark-validate-links',
507+ '',
508+ 'github.md',
509+ ' 5:37-5:51 warning Link to unknown heading: `world` missing-heading remark-validate-links',
510+ ' 21:34-21:100 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
511+ ' 23:34-23:82 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
512+ ' 25:12-25:81 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
513+ ' 27:10-27:37 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
514+ ' 29:10-29:35 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
515+ ' 41:10-41:41 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
516+ ' 43:10-43:39 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
517+ ' 45:10-45:80 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
518+ ' 47:10-47:83 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
519+ ' 49:10-49:40 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
520+ ' 49:10-49:40 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
521+ ' 51:10-51:38 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
522+ ' 51:10-51:38 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
523+ ' 53:10-53:79 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
524+ ' 53:10-53:79 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
525+ ' 55:10-55:82 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
526+ ' 55:10-55:82 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
527+ '',
528+ '⚠ 31 warnings',
529+ ''
530+ ].join('\n')
531+ ],
532+ 'should work'
453533 )
534+ }
454535
455536 function clean() {
456537 rimraf.sync('./.git')
457538 }
458539 })
459540
460− t.test('should fail w/o Git repository', function(st) {
541+ t.test('should fail w/o Git repository', function (st) {
461542 st.plan(1)
462543
463544 fs.renameSync('../../.git', '../../.git.bak')
464545
465− execa(bin, [
466− '--no-config',
467− '--no-ignore',
468− '--use',
469− '../..',
470− '--use',
471− '../sort',
472− 'github.md'
473− ]).then(
474− function() {
475− clean()
476− st.fail('should not work')
477− },
478− function(err) {
479− clean()
480− st.ok(/not a git repository/i.test(err), 'should fail')
481− }
546+ childProcess.exec(
547+ [
548+ bin,
549+ '--no-config',
550+ '--no-ignore',
551+ '--use',
552+ '../..',
553+ '--use',
554+ '../sort',
555+ 'github.md'
556+ ].join(' '),
557+ onexec
482558 )
483559
484− function clean() {
560+ function onexec(err) {
485561 fs.renameSync('../../.git.bak', '../../.git')
562+ st.ok(/not a git repository/i.test(err), 'should fail')
486563 }
487564 })
488565
489− t.test('should fail w/o Git repository w/o remote', function(st) {
566+ t.test('should fail w/o Git repository w/o remote', function (st) {
490567 st.plan(1)
491568
492− Promise.resolve()
493− .then(function() {
494− return execa('git', ['init'])
495− })
496− .then(function() {
497− return execa(bin, [
498− '--no-config',
499− '--no-ignore',
500− '--use',
501− '../..',
502− 'github.md'
503− ])
504− })
505− .then(
506− function() {
507− clean()
508− st.fail('should not work')
509− },
510− function(err) {
511− clean()
512− st.ok(/Could not find remote origin/.test(err), 'should fail')
513− }
514− )
569+ childProcess.exec('git init', oninit)
515570
516− function clean() {
571+ function oninit(err) {
572+ if (err) {
573+ t.ifErr(err)
574+ } else {
575+ childProcess.exec(
576+ [
577+ bin,
578+ '--no-config',
579+ '--no-ignore',
580+ '--use',
581+ '../..',
582+ 'github.md'
583+ ].join(' '),
584+ onexec
585+ )
586+ }
587+ }
588+
589+ function onexec(err) {
517590 rimraf.sync('./.git')
591+ st.ok(/Could not find remote origin/.test(err), 'should fail')
518592 }
519593 })
520594
521− t.test('should work w/o Git repository w/ repo', function(st) {
595+ t.test('should work w/o Git repository w/ repo', function (st) {
522596 st.plan(1)
523597
524598 fs.renameSync('../../.git', '../../.git.bak')
525599
526− execa(bin, [
527− '--no-config',
528− '--no-ignore',
529− '--use',
530− '../..=repository:"wooorm/test"',
531− '--use',
532− '../sort',
533− 'small.md'
534− ]).then(
535− function(result) {
536− clean()
537− st.equal(
538− strip(result.stderr),
600+ childProcess.exec(
601+ [
602+ bin,
603+ '--no-config',
604+ '--no-ignore',
605+ '--use',
606+ '"../..=repository:\\"wooorm/test\\""',
607+ '--use',
608+ '../sort',
609+ 'small.md'
610+ ].join(' '),
611+ onexec
612+ )
613+
614+ function onexec(err, stdout, stderr) {
615+ fs.renameSync('../../.git.bak', '../../.git')
616+ st.deepEqual(
617+ [err, strip(stderr)],
618+ [
619+ null,
539620 [
540621 'small.md',
541622 ' 5:13-5:27 warning Link to unknown heading: `world` missing-heading remark-validate-links',
542623 '',
543− '⚠ 1 warning'
544− ].join('\n'),
545− 'should work'
546− )
547− },
548− function(err) {
549− clean()
550− st.error(err, 'shoult not fail')
551− }
552− )
553−
554− function clean() {
555− fs.renameSync('../../.git.bak', '../../.git')
624+ '⚠ 1 warning',
625+ ''
626+ ].join('\n')
627+ ],
628+ 'should work'
629+ )
556630 }
557631 })
558632
559− t.test('should work w/o Git repository w/ remote', function(st) {
633+ t.test('should work w/o Git repository w/ remote', function (st) {
560634 st.plan(1)
561635
562636 fs.renameSync('../../.git', '../../.git.bak')
563637
564− execa(bin, [
565− '--no-config',
566− '--no-ignore',
567− '--use',
568− '../..=repository:{remote:"wooorm/test"}',
569− 'small.md'
570− ]).then(
571− function(result) {
572− clean()
573− st.equal(
574− strip(result.stderr),
638+ childProcess.exec(
639+ [
640+ bin,
641+ '--no-config',
642+ '--no-ignore',
643+ '--use',
644+ '"../..=repository:{remote:\\"wooorm/test\\"}"',
645+ 'small.md'
646+ ].join(' '),
647+ onexec
648+ )
649+
650+ function onexec(err, stdout, stderr) {
651+ fs.renameSync('../../.git.bak', '../../.git')
652+ st.deepEqual(
653+ [err, strip(stderr)],
654+ [
655+ null,
575656 [
576657 'small.md',
577658 ' 5:13-5:27 warning Link to unknown heading: `world` missing-heading remark-validate-links',
578659 '',
579− '⚠ 1 warning'
580− ].join('\n'),
581− 'should work'
582− )
583− },
584− function(err) {
585− clean()
586− st.error(err, 'shoult not fail')
587− }
588− )
589−
590− function clean() {
591− fs.renameSync('../../.git.bak', '../../.git')
660+ '⚠ 1 warning',
661+ ''
662+ ].join('\n')
663+ ],
664+ 'should work'
665+ )
592666 }
593667 })
594668
595− t.test('should work w/o Git repository w/ remote and root', function(st) {
669+ t.test('should work w/o Git repository w/ remote and root', function (st) {
596670 st.plan(1)
597671
598672 fs.renameSync('../../.git', '../../.git.bak')
599673
600− execa(bin, [
601− '--no-config',
602− '--no-ignore',
603− '--use',
604− '../..=repository:"wooorm/test",root:"../"',
605− 'small.md'
606− ]).then(
607− function(result) {
608− clean()
609− st.equal(
610− strip(result.stderr),
674+ childProcess.exec(
675+ [
676+ bin,
677+ '--no-config',
678+ '--no-ignore',
679+ '--use',
680+ '"../..=repository:\\"wooorm/test\\",root:\\"../\\""',
681+ 'small.md'
682+ ].join(' '),
683+ onexec
684+ )
685+
686+ function onexec(err, stdout, stderr) {
687+ fs.renameSync('../../.git.bak', '../../.git')
688+ st.deepEqual(
689+ [err, strip(stderr)],
690+ [
691+ null,
611692 [
612693 'small.md',
613694 ' 5:13-5:27 warning Link to unknown heading: `world` missing-heading remark-validate-links',
614695 '',
615− '⚠ 1 warning'
616− ].join('\n'),
617− 'should work'
618− )
619− },
620− function(err) {
621− clean()
622− st.error(err, 'shoult not fail')
623− }
624− )
625−
626− function clean() {
627− fs.renameSync('../../.git.bak', '../../.git')
696+ '⚠ 1 warning',
697+ ''
698+ ].join('\n')
699+ ],
700+ 'should work'
701+ )
628702 }
629703 })
630704
631− t.test('should work with `repository:false`', function(st) {
705+ t.test('should work with `repository:false`', function (st) {
632706 st.plan(1)
633707
634708 fs.renameSync('../../.git', '../../.git.bak')
635709
636− execa(bin, [
637− '--no-config',
638− '--no-ignore',
639− '--use',
640− '../..=repository:false',
641− '--use',
642− '../sort',
643− 'github.md',
644− 'examples/github.md'
645− ]).then(
646− function(result) {
647− clean()
648− st.equal(
649− strip(result.stderr),
710+ childProcess.exec(
711+ [
712+ bin,
713+ '--no-config',
714+ '--no-ignore',
715+ '--use',
716+ '"../..=repository:false"',
717+ '--use',
718+ '../sort',
719+ 'github.md',
720+ 'examples/github.md'
721+ ].join(' '),
722+ onexec
723+ )
724+
725+ function onexec(err, stdout, stderr) {
726+ fs.renameSync('../../.git.bak', '../../.git')
727+ st.deepEqual(
728+ [err, strip(stderr)],
729+ [
730+ null,
650731 [
651732 'examples/github.md',
652733 ' 5:37-5:51 warning Link to unknown heading: `world` missing-heading remark-validate-links',
@@ -665,383 +746,552 @@ test('remark-validate-links', function(t) {
665746 ' 49:10-49:40 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
666747 ' 51:10-51:38 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
667748 ' 51:10-51:38 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
749+ ' 71:41-71:56 warning Link to unknown heading: `readme` missing-heading remark-validate-links',
668750 '',
669− '⚠ 14 warnings'
670− ].join('\n'),
671− 'should report'
672− )
673− },
674− function(err) {
675− clean()
676− st.error(err)
677− }
751+ '⚠ 15 warnings',
752+ ''
753+ ].join('\n')
754+ ],
755+ 'should work'
756+ )
757+ }
758+ })
759+
760+ t.test('should work when finding non-hosted Git remotes', function (st) {
761+ st.plan(1)
762+
763+ childProcess.exec(
764+ [
765+ bin,
766+ '--no-config',
767+ '--no-ignore',
768+ '--use',
769+ '"../..=repository:\\"ssh://git@domain.com/user/project.git\\""',
770+ '--use',
771+ '../sort',
772+ 'small.md'
773+ ].join(' '),
774+ onexec
678775 )
679776
680− function clean() {
681− fs.renameSync('../../.git.bak', '../../.git')
777+ function onexec(err, stdout, stderr) {
778+ st.deepEqual(
779+ [err, strip(stderr)],
780+ [
781+ null,
782+ [
783+ 'small.md',
784+ ' 5:13-5:27 warning Link to unknown heading: `world` missing-heading remark-validate-links',
785+ '',
786+ '⚠ 1 warning',
787+ ''
788+ ].join('\n')
789+ ],
790+ 'should work'
791+ )
682792 }
683793 })
684794
685− t.test('should work when finding non-hosted Git remotes', function(st) {
795+ t.test('should support a GitLab shortcode', function (st) {
686796 st.plan(1)
687797
688− execa(bin, [
689− '--no-config',
690− '--no-ignore',
691− '--use',
692− '../..=repository:"ssh://git@domain.com/user/project.git"',
693− '--use',
694− '../sort',
695− 'small.md'
696− ]).then(function(result) {
697− st.equal(
698− strip(result.stderr),
798+ childProcess.exec(
799+ [
800+ bin,
801+ '--no-config',
802+ '--no-ignore',
803+ '--use',
804+ '"../..=repository:\\"gitlab:wooorm/test\\""',
805+ '--use',
806+ '../sort',
807+ 'gitlab.md'
808+ ].join(' '),
809+ onexec
810+ )
811+
812+ function onexec(err, stdout, stderr) {
813+ st.deepEqual(
814+ [err, strip(stderr)],
699815 [
700− 'small.md',
701− ' 5:13-5:27 warning Link to unknown heading: `world` missing-heading remark-validate-links',
702− '',
703− '⚠ 1 warning'
704− ].join('\n'),
705− 'should report'
816+ null,
817+ [
818+ 'gitlab.md',
819+ ' 5:37-5:51 warning Link to unknown heading: `world` missing-heading remark-validate-links',
820+ ' 19:34-19:100 warning Link to unknown file: `examples/world.md`. Did you mean `examples/gitlab.md` missing-file remark-validate-links',
821+ ' 21:12-21:81 warning Link to unknown file: `examples/world.md`. Did you mean `examples/gitlab.md` missing-file remark-validate-links',
822+ ' 23:10-23:37 warning Link to unknown file: `examples/world.md`. Did you mean `examples/gitlab.md` missing-file remark-validate-links',
823+ ' 25:10-25:35 warning Link to unknown file: `examples/world.md`. Did you mean `examples/gitlab.md` missing-file remark-validate-links',
824+ ' 37:10-37:41 warning Link to unknown heading in `examples/gitlab.md`: `world` missing-heading-in-file remark-validate-links',
825+ ' 39:10-39:39 warning Link to unknown heading in `examples/gitlab.md`: `world` missing-heading-in-file remark-validate-links',
826+ ' 41:10-41:80 warning Link to unknown heading in `examples/gitlab.md`: `world` missing-heading-in-file remark-validate-links',
827+ ' 43:10-43:83 warning Link to unknown heading in `examples/gitlab.md`: `world` missing-heading-in-file remark-validate-links',
828+ ' 45:10-45:40 warning Link to unknown file: `examples/world.md`. Did you mean `examples/gitlab.md` missing-file remark-validate-links',
829+ ' 45:10-45:40 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
830+ ' 47:10-47:38 warning Link to unknown file: `examples/world.md`. Did you mean `examples/gitlab.md` missing-file remark-validate-links',
831+ ' 47:10-47:38 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
832+ ' 49:10-49:79 warning Link to unknown file: `examples/world.md`. Did you mean `examples/gitlab.md` missing-file remark-validate-links',
833+ ' 49:10-49:79 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
834+ ' 51:10-51:82 warning Link to unknown file: `examples/world.md`. Did you mean `examples/gitlab.md` missing-file remark-validate-links',
835+ ' 51:10-51:82 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
836+ '',
837+ '⚠ 17 warnings',
838+ ''
839+ ].join('\n')
840+ ],
841+ 'should work'
706842 )
707− }, st.error)
843+ }
844+ })
845+
846+ t.test('should support a Bitbucket shortcode', function (st) {
847+ st.plan(1)
848+
849+ childProcess.exec(
850+ [
851+ bin,
852+ '--no-config',
853+ '--no-ignore',
854+ '--use',
855+ '"../..=repository:\\"bitbucket:wooorm/test\\""',
856+ '--use',
857+ '../sort',
858+ 'bitbucket.md'
859+ ].join(' '),
860+ onexec
861+ )
862+
863+ function onexec(err, stdout, stderr) {
864+ st.deepEqual(
865+ [err, strip(stderr)],
866+ [
867+ null,
868+ [
869+ 'bitbucket.md',
870+ ' 5:37-5:67 warning Link to unknown heading: `world` missing-heading remark-validate-links',
871+ ' 21:34-21:102 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
872+ ' 23:12-23:83 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
873+ ' 25:10-25:37 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
874+ ' 27:10-27:35 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
875+ ' 39:10-39:60 warning Link to unknown heading in `examples/bitbucket.md`: `world` missing-heading-in-file remark-validate-links',
876+ ' 41:10-41:58 warning Link to unknown heading in `examples/bitbucket.md`: `world` missing-heading-in-file remark-validate-links',
877+ ' 43:10-43:101 warning Link to unknown heading in `examples/bitbucket.md`: `world` missing-heading-in-file remark-validate-links',
878+ ' 45:10-45:104 warning Link to unknown heading in `examples/bitbucket.md`: `world` missing-heading-in-file remark-validate-links',
879+ ' 47:10-47:56 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
880+ ' 47:10-47:56 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
881+ ' 49:10-49:54 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
882+ ' 49:10-49:54 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
883+ ' 51:10-51:97 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
884+ ' 51:10-51:97 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
885+ ' 53:10-53:100 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
886+ ' 53:10-53:100 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
887+ '',
888+ '⚠ 17 warnings',
889+ ''
890+ ].join('\n')
891+ ],
892+ 'should work'
893+ )
894+ }
708895 })
709896
710− t.test('should support a GitLab shortcode', function(st) {
897+ t.test('should suggest similar links', function (st) {
711898 st.plan(1)
712899
713− execa(bin, [
714− '--no-config',
715− '--no-ignore',
716− '--use',
717− '../..=repository:"gitlab:wooorm/test"',
718− '--use',
719− '../sort',
720− 'gitlab.md'
721− ]).then(function(result) {
722− st.equal(
723− strip(result.stderr),
900+ childProcess.exec(
901+ [
902+ bin,
903+ '--no-config',
904+ '--no-ignore',
905+ '--use',
906+ '../..',
907+ '--use',
908+ '../sort',
909+ 'suggestions.md'
910+ ].join(' '),
911+ onexec
912+ )
913+
914+ function onexec(err, stdout, stderr) {
915+ st.deepEqual(
916+ [err, strip(stderr)],
724917 [
725− 'gitlab.md',
726− ' 5:37-5:51 warning Link to unknown heading: `world` missing-heading remark-validate-links',
727− ' 19:34-19:102 warning Link to unknown file: `examples/world.md`. Did you mean `examples/gitlab.md` missing-file remark-validate-links',
728− ' 21:12-21:81 warning Link to unknown file: `examples/world.md`. Did you mean `examples/gitlab.md` missing-file remark-validate-links',
729− ' 23:10-23:37 warning Link to unknown file: `examples/world.md`. Did you mean `examples/gitlab.md` missing-file remark-validate-links',
730− ' 25:10-25:35 warning Link to unknown file: `examples/world.md`. Did you mean `examples/gitlab.md` missing-file remark-validate-links',
731− ' 37:10-37:41 warning Link to unknown heading in `examples/gitlab.md`: `world` missing-heading-in-file remark-validate-links',
732− ' 39:10-39:39 warning Link to unknown heading in `examples/gitlab.md`: `world` missing-heading-in-file remark-validate-links',
733− ' 41:10-41:82 warning Link to unknown heading in `examples/gitlab.md`: `world` missing-heading-in-file remark-validate-links',
734− ' 43:10-43:83 warning Link to unknown heading in `examples/gitlab.md`: `world` missing-heading-in-file remark-validate-links',
735− ' 45:10-45:40 warning Link to unknown file: `examples/world.md`. Did you mean `examples/gitlab.md` missing-file remark-validate-links',
736− ' 45:10-45:40 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
737− ' 47:10-47:38 warning Link to unknown file: `examples/world.md`. Did you mean `examples/gitlab.md` missing-file remark-validate-links',
738− ' 47:10-47:38 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
739− ' 49:10-49:81 warning Link to unknown file: `examples/world.md`. Did you mean `examples/gitlab.md` missing-file remark-validate-links',
740− ' 49:10-49:81 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
741− ' 51:10-51:82 warning Link to unknown file: `examples/world.md`. Did you mean `examples/gitlab.md` missing-file remark-validate-links',
742− ' 51:10-51:82 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
743− '',
744− '⚠ 17 warnings'
745− ].join('\n'),
746− 'should report'
918+ null,
919+ [
920+ 'suggestions.md',
921+ ' 3:22-3:37 warning Link to unknown heading: `helloo`. Did you mean `hello` missing-heading remark-validate-links',
922+ ' 7:17-7:39 warning Link to unknown heading in `github.md`: `fiiiles`. Did you mean `files` missing-heading-in-file remark-validate-links',
923+ '',
924+ '⚠ 2 warnings',
925+ ''
926+ ].join('\n')
927+ ],
928+ 'should work'
747929 )
748− }, st.error)
930+ }
749931 })
750932
751− t.test('should support a Bitbucket shortcode', function(st) {
933+ t.test('should recognise links to particular lines', function (st) {
752934 st.plan(1)
753935
754− execa(bin, [
755− '--no-config',
756− '--no-ignore',
757− '--use',
758− '../..=repository:"bitbucket:wooorm/test"',
759− '--use',
760− '../sort',
761− 'bitbucket.md'
762− ]).then(function(result) {
763− st.equal(
764− strip(result.stderr),
936+ childProcess.exec(
937+ [
938+ bin,
939+ '--no-config',
940+ '--no-ignore',
941+ '--use',
942+ '"../..=repository:\\"wooorm/test\\""',
943+ '--use',
944+ '../sort',
945+ 'line-links.md'
946+ ].join(' '),
947+ onexec
948+ )
949+
950+ function onexec(err, stdout, stderr) {
951+ st.deepEqual(
952+ [err, strip(stderr)],
765953 [
766− 'bitbucket.md',
767− ' 5:37-5:67 warning Link to unknown heading: `world` missing-heading remark-validate-links',
768− ' 21:34-21:104 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
769− ' 23:12-23:83 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
770− ' 25:10-25:37 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
771− ' 27:10-27:35 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
772− ' 39:10-39:60 warning Link to unknown heading in `examples/bitbucket.md`: `world` missing-heading-in-file remark-validate-links',
773− ' 41:10-41:58 warning Link to unknown heading in `examples/bitbucket.md`: `world` missing-heading-in-file remark-validate-links',
774− ' 43:10-43:103 warning Link to unknown heading in `examples/bitbucket.md`: `world` missing-heading-in-file remark-validate-links',
775− ' 45:10-45:104 warning Link to unknown heading in `examples/bitbucket.md`: `world` missing-heading-in-file remark-validate-links',
776− ' 47:10-47:56 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
777− ' 47:10-47:56 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
778− ' 49:10-49:54 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
779− ' 49:10-49:54 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
780− ' 51:10-51:99 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
781− ' 51:10-51:99 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
782− ' 53:10-53:100 warning Link to unknown file: `examples/world.md` missing-file remark-validate-links',
783− ' 53:10-53:100 warning Link to unknown heading in `examples/world.md`: `hello` missing-heading-in-file remark-validate-links',
784− '',
785− '⚠ 17 warnings'
786− ].join('\n'),
787− 'should report'
954+ null,
955+ [
956+ 'line-links.md',
957+ ' 5:9-5:61 warning Link to unknown file: `examples/missing.js` missing-file remark-validate-links',
958+ ' 9:1-9:69 warning Link to unknown file: `examples/missing.js` missing-file remark-validate-links',
959+ '',
960+ '⚠ 2 warnings',
961+ ''
962+ ].join('\n')
963+ ],
964+ 'should work'
788965 )
789− }, st.error)
966+ }
790967 })
791968
792− t.test('should suggest similar links', function(st) {
969+ t.test('should recognise links with encoded URLs', function (st) {
793970 st.plan(1)
794971
795− execa(bin, [
796− '--no-config',
797− '--no-ignore',
798− '--use',
799− '../..',
800− '--use',
801− '../sort',
802− 'suggestions.md'
803− ]).then(function(result) {
804− st.equal(
805− strip(result.stderr),
972+ childProcess.exec(
973+ [
974+ bin,
975+ '--no-config',
976+ '--no-ignore',
977+ '--use',
978+ '"../..=repository:\\"wooorm/test\\""',
979+ '--use',
980+ '../sort',
981+ 'weird-characters.md'
982+ ].join(' '),
983+ onexec
984+ )
985+
986+ function onexec(err, stdout, stderr) {
987+ st.deepEqual(
988+ [err, strip(stderr)],
806989 [
807− 'suggestions.md',
808− ' 3:22-3:37 warning Link to unknown heading: `helloo`. Did you mean `hello` missing-heading remark-validate-links',
809− ' 7:17-7:39 warning Link to unknown heading in `github.md`: `fiiiles`. Did you mean `files` missing-heading-in-file remark-validate-links',
810− '',
811− '⚠ 2 warnings'
812− ].join('\n'),
813− 'should report'
990+ null,
991+ [
992+ 'weird-characters.md',
993+ ' 11:17-11:87 warning Link to unknown file: `examples/missing#characters.md`. Did you mean `examples/weird#characters.md` missing-file remark-validate-links',
994+ ' 13:17-13:93 warning Link to unknown file: `examples/missing#character/readme.md`. Did you mean `examples/weird#character/readme.md` missing-file remark-validate-links',
995+ ' 15:17-15:114 warning Link to unknown heading in `examples/weird#characters.md`: `world` missing-heading-in-file remark-validate-links',
996+ ' 17:17-17:120 warning Link to unknown heading in `examples/weird#character/readme.md`: `world` missing-heading-in-file remark-validate-links',
997+ '',
998+ '⚠ 4 warnings',
999+ ''
1000+ ].join('\n')
1001+ ],
1002+ 'should work'
8141003 )
815− }, st.error)
1004+ }
8161005 })
8171006
818− t.test('should recognise links to particular lines', function(st) {
1007+ t.test('should support folders', function (st) {
8191008 st.plan(1)
8201009
821− execa(bin, [
822− '--no-config',
823− '--no-ignore',
824− '--use',
825− '../..=repository:"wooorm/test"',
826− '--use',
827− '../sort',
828− 'line-links.md'
829− ]).then(function(result) {
830− st.equal(
831− strip(result.stderr),
1010+ childProcess.exec(
1011+ [
1012+ bin,
1013+ '--no-config',
1014+ '--no-ignore',
1015+ '--use',
1016+ '"../..=repository:\\"wooorm/test\\""',
1017+ '--use',
1018+ '../sort',
1019+ 'folder.md'
1020+ ].join(' '),
1021+ onexec
1022+ )
1023+
1024+ function onexec(err, stdout, stderr) {
1025+ st.deepEqual(
1026+ [err, strip(stderr)],
8321027 [
833− 'line-links.md',
834− ' 5:9-5:61 warning Link to unknown file: `examples/missing.js` missing-file remark-validate-links',
835− ' 9:1-9:71 warning Link to unknown file: `examples/missing.js` missing-file remark-validate-links',
836− '',
837− '⚠ 2 warnings'
838− ].join('\n'),
839− 'should report'
1028+ null,
1029+ [
1030+ 'folder.md',
1031+ ' 9:1-9:40 warning Link to unknown heading in `folder/readme.markdown`: `missing` missing-heading-in-file remark-validate-links',
1032+ ' 17:1-17:24 warning Link to unknown heading in `folder`: `missing` missing-heading-in-file remark-validate-links',
1033+ ' 21:1-21:25 warning Link to unknown file: `missing` missing-file remark-validate-links',
1034+ ' 21:1-21:25 warning Link to unknown heading in `missing`: `missing` missing-heading-in-file remark-validate-links',
1035+ ' 23:1-23:39 warning Link to unknown heading in `folder-without-readme`: `missing` missing-heading-in-file remark-validate-links',
1036+ '',
1037+ '⚠ 5 warnings',
1038+ ''
1039+ ].join('\n')
1040+ ],
1041+ 'should work'
8401042 )
841− }, st.error)
1043+ }
8421044 })
8431045
844− t.test('should recognise links with encoded URLs', function(st) {
1046+ t.test('should warn on files as folders', function (st) {
8451047 st.plan(1)
8461048
847− execa(bin, [
848− '--no-config',
849− '--no-ignore',
850− '--use',
851− '../..=repository:"wooorm/test"',
852− '--use',
853− '../sort',
854− 'weird-characters.md'
855− ]).then(function(result) {
856− st.equal(
857− strip(result.stderr),
1049+ childProcess.exec(
1050+ [
1051+ bin,
1052+ '--no-config',
1053+ '--no-ignore',
1054+ '--use',
1055+ '../..',
1056+ '--use',
1057+ '../sort',
1058+ 'file-as-folder.md'
1059+ ].join(' '),
1060+ onexec
1061+ )
1062+
1063+ function onexec(err, stdout, stderr) {
1064+ st.deepEqual(
1065+ [err, strip(stderr)],
8581066 [
859− 'weird-characters.md',
860− ' 11:17-11:87 warning Link to unknown file: `examples/missing#characters.md`. Did you mean `examples/weird#characters.md` missing-file remark-validate-links',
861− ' 13:17-13:93 warning Link to unknown file: `examples/missing#character/readme.md`. Did you mean `examples/weird#character/readme.md` missing-file remark-validate-links',
862− ' 15:17-15:114 warning Link to unknown heading in `examples/weird#characters.md`: `world` missing-heading-in-file remark-validate-links',
863− ' 17:17-17:120 warning Link to unknown heading in `examples/weird#character/readme.md`: `world` missing-heading-in-file remark-validate-links',
864− '',
865− '⚠ 4 warnings'
866− ].join('\n'),
867− 'should report'
1067+ null,
1068+ [
1069+ 'file-as-folder.md',
1070+ ' 1:1-1:28 warning Link to unknown file: `file-as-folder.md/other`. Did you mean `file-as-folder.md` missing-file remark-validate-links',
1071+ '',
1072+ '⚠ 1 warning',
1073+ ''
1074+ ].join('\n')
1075+ ],
1076+ 'should work'
8681077 )
869− }, st.error)
1078+ }
8701079 })
8711080
872− t.test('should check images', function(st) {
1081+ t.test('should check images', function (st) {
8731082 st.plan(1)
8741083
875− execa(bin, [
876− '--no-config',
877− '--no-ignore',
878− '--use',
879− '../..=repository:"wooorm/test"',
880− '--use',
881− '../sort',
882− 'images.md'
883− ]).then(function(result) {
884− st.equal(
885− strip(result.stderr),
1084+ childProcess.exec(
1085+ [
1086+ bin,
1087+ '--no-config',
1088+ '--no-ignore',
1089+ '--use',
1090+ '"../..=repository:\\"wooorm/test\\""',
1091+ '--use',
1092+ '../sort',
1093+ 'images.md'
1094+ ].join(' '),
1095+ onexec
1096+ )
1097+
1098+ function onexec(err, stdout, stderr) {
1099+ st.deepEqual(
1100+ [err, strip(stderr)],
8861101 [
887− 'images.md',
888− ' 19:10-19:50 warning Link to unknown file: `examples/missing.jpg`. Did you mean `examples/image.jpg` missing-file remark-validate-links',
889− ' 21:12-21:42 warning Link to unknown file: `examples/missing.jpg`. Did you mean `examples/image.jpg` missing-file remark-validate-links',
890− ' 23:10-23:91 warning Link to unknown file: `examples/missing.jpg`. Did you mean `examples/image.jpg` missing-file remark-validate-links',
891− ' 35:1-35:38 warning Link to unknown file: `examples/missing.jpg`. Did you mean `examples/image.jpg` missing-file remark-validate-links',
892− ' 37:1-37:79 warning Link to unknown file: `examples/missing.jpg`. Did you mean `examples/image.jpg` missing-file remark-validate-links',
893− '',
894− '⚠ 5 warnings'
895− ].join('\n'),
896− 'should report'
1102+ null,
1103+ [
1104+ 'images.md',
1105+ ' 19:10-19:50 warning Link to unknown file: `examples/missing.jpg`. Did you mean `examples/image.jpg` missing-file remark-validate-links',
1106+ ' 21:12-21:42 warning Link to unknown file: `examples/missing.jpg`. Did you mean `examples/image.jpg` missing-file remark-validate-links',
1107+ ' 23:10-23:89 warning Link to unknown file: `examples/missing.jpg`. Did you mean `examples/image.jpg` missing-file remark-validate-links',
1108+ ' 35:1-35:38 warning Link to unknown file: `examples/missing.jpg`. Did you mean `examples/image.jpg` missing-file remark-validate-links',
1109+ ' 37:1-37:77 warning Link to unknown file: `examples/missing.jpg`. Did you mean `examples/image.jpg` missing-file remark-validate-links',
1110+ '',
1111+ '⚠ 5 warnings',
1112+ ''
1113+ ].join('\n')
1114+ ],
1115+ 'should work'
8971116 )
898− }, st.error)
1117+ }
8991118 })
9001119
901− t.test('should support query parameters', function(st) {
1120+ t.test('should support query parameters', function (st) {
9021121 st.plan(1)
9031122
904− execa(bin, [
905− '--no-config',
906− '--no-ignore',
907− '--use',
908− '../..=repository:"wooorm/test"',
909− '--use',
910− '../sort',
911− 'query-params.md'
912− ]).then(
913− function(result) {
914− st.equal(
915− strip(result.stderr),
1123+ childProcess.exec(
1124+ [
1125+ bin,
1126+ '--no-config',
1127+ '--no-ignore',
1128+ '--use',
1129+ '"../..=repository:\\"wooorm/test\\""',
1130+ '--use',
1131+ '../sort',
1132+ 'query-params.md'
1133+ ].join(' '),
1134+ onexec
1135+ )
1136+
1137+ function onexec(err, stdout, stderr) {
1138+ st.deepEqual(
1139+ [err, strip(stderr)],
1140+ [
1141+ null,
9161142 [
9171143 'query-params.md',
9181144 ' 9:33-9:55 warning Link to unknown heading: `query-params?`. Did you mean `query-params` missing-heading remark-validate-links',
9191145 '',
920− '⚠ 1 warning'
921− ].join('\n'),
922− 'should report'
923− )
924− },
925− function(err) {
926− st.error(err, 'should not fail')
927− }
928− )
1146+ '⚠ 1 warning',
1147+ ''
1148+ ].join('\n')
1149+ ],
1150+ 'should work'
1151+ )
1152+ }
9291153 })
9301154
931− t.test('should support case insensitive headings', function(st) {
1155+ t.test('should support case insensitive headings', function (st) {
9321156 st.plan(1)
9331157
934− execa(bin, [
935− '--no-config',
936− '--no-ignore',
937− '--use',
938− '../..',
939− '--use',
940− '../sort',
941− 'case-insensitive-headings.md'
942− ]).then(
943− function(result) {
944− st.equal(
945− strip(result.stderr),
1158+ childProcess.exec(
1159+ [
1160+ bin,
1161+ '--no-config',
1162+ '--no-ignore',
1163+ '--use',
1164+ '../..',
1165+ '--use',
1166+ '../sort',
1167+ 'case-insensitive-headings.md'
1168+ ].join(' '),
1169+ onexec
1170+ )
1171+
1172+ function onexec(err, stdout, stderr) {
1173+ st.deepEqual(
1174+ [err, strip(stderr)],
1175+ [
1176+ null,
9461177 [
9471178 'case-insensitive-headings.md',
9481179 ' 5:13-5:27 warning Link to unknown heading: `world` missing-heading remark-validate-links',
9491180 ' 9:16-9:48 warning Link to unknown heading in `examples/github.md`: `world` missing-heading-in-file remark-validate-links',
9501181 '',
951− '⚠ 2 warnings'
952− ].join('\n'),
953− 'should report'
954− )
955− },
956− function(err) {
957− st.error(err, 'should not fail')
958− }
959− )
1182+ '⚠ 2 warnings',
1183+ ''
1184+ ].join('\n')
1185+ ],
1186+ 'should work'
1187+ )
1188+ }
9601189 })
9611190
962− t.test('should ignore external links', function(st) {
1191+ t.test('should ignore external links', function (st) {
9631192 st.plan(1)
9641193
965− execa(bin, [
966− '--no-config',
967− '--no-ignore',
968− '--use',
969− '../..=repository:"wooorm/test"',
970− '--use',
971− '../sort',
972− 'external.md'
973− ]).then(function(result) {
974− st.equal(
975− strip(result.stderr),
976− 'external.md: no issues found',
977− 'should report'
1194+ childProcess.exec(
1195+ [
1196+ bin,
1197+ '--no-config',
1198+ '--no-ignore',
1199+ '--use',
1200+ '"../..=repository:\\"wooorm/test\\""',
1201+ '--use',
1202+ '../sort',
1203+ 'external.md'
1204+ ].join(' '),
1205+ onexec
1206+ )
1207+
1208+ function onexec(err, stdout, stderr) {
1209+ st.deepEqual(
1210+ [err, strip(stderr)],
1211+ [null, 'external.md: no issues found\n'],
1212+ 'should work'
9781213 )
979− }, st.error)
1214+ }
9801215 })
9811216
982− t.test('should ignore external links (without repo)', function(st) {
1217+ t.test('should ignore external links (without repo)', function (st) {
9831218 st.plan(1)
9841219
985− execa(bin, [
986− '--no-config',
987− '--no-ignore',
988− '--use',
989− '../..=repository:false',
990− '--use',
991− '../sort',
992− 'external.md'
993− ]).then(function(result) {
994− st.equal(
995− strip(result.stderr),
996− 'external.md: no issues found',
997− 'should report'
1220+ childProcess.exec(
1221+ [
1222+ bin,
1223+ '--no-config',
1224+ '--no-ignore',
1225+ '--use',
1226+ '../..=repository:false',
1227+ '--use',
1228+ '../sort',
1229+ 'external.md'
1230+ ].join(' '),
1231+ onexec
1232+ )
1233+
1234+ function onexec(err, stdout, stderr) {
1235+ st.deepEqual(
1236+ [err, strip(stderr)],
1237+ [null, 'external.md: no issues found\n'],
1238+ 'should work'
9981239 )
999− }, st.error)
1240+ }
10001241 })
10011242
1002− t.test('should support self-hosted Git solutions', function(st) {
1243+ t.test('should support self-hosted Git solutions', function (st) {
10031244 st.plan(1)
10041245
1005− Promise.resolve()
1006− .then(function() {
1007− return execa('git', ['init'])
1008− })
1009− .then(function() {
1010− return execa('git', [
1011− 'remote',
1012− 'add',
1013− 'origin',
1014− 'git@gitlab.acme.company:acme/project.git'
1015− ])
1016− })
1017− .then(function() {
1018− return execa(bin, [
1019− '--no-config',
1020− '--no-ignore',
1021− '--use',
1022− '../..=urlConfig:{hostname:"gitlab.acme.com",prefix:"/acme/project/blob/",headingPrefix:"#",lines:true}',
1023− 'self-hosted.md'
1024− ])
1025− })
1026− .then(
1027− function(result) {
1028− clean()
1029− st.equal(
1030− strip(result.stderr),
1031− [
1032− 'self-hosted.md',
1033− ' 5:1-5:82 warning Link to unknown heading: `world` missing-heading remark-validate-links',
1034− '',
1035− '⚠ 1 warning'
1036− ].join('\n'),
1037− 'should report'
1038− )
1039− },
1040− function(err) {
1041− clean()
1042− st.error(err)
1043− }
1246+ childProcess.exec('git init', oninit)
1247+
1248+ function oninit(err) {
1249+ if (err) {
1250+ t.ifErr(err)
1251+ } else {
1252+ childProcess.exec(
1253+ 'git remote add origin git@gitlab.acme.company:acme/project.git',
1254+ onremote
1255+ )
1256+ }
1257+ }
1258+
1259+ function onremote(err) {
1260+ if (err) {
1261+ clean()
1262+ t.ifErr(err)
1263+ } else {
1264+ childProcess.exec(
1265+ [
1266+ bin,
1267+ '--no-config',
1268+ '--no-ignore',
1269+ '--use',
1270+ '"../..=urlConfig:{hostname:\\"gitlab.acme.com\\",prefix:\\"/acme/project/blob/\\",headingPrefix:\\"#\\",lines:true}"',
1271+ 'self-hosted.md'
1272+ ].join(' '),
1273+ onexec
1274+ )
1275+ }
1276+ }
1277+
1278+ function onexec(err, stdout, stderr) {
1279+ clean()
1280+ st.deepEqual(
1281+ [err, strip(stderr)],
1282+ [
1283+ null,
1284+ [
1285+ 'self-hosted.md',
1286+ ' 5:1-5:80 warning Link to unknown heading: `world` missing-heading remark-validate-links',
1287+ '',
1288+ '⚠ 1 warning',
1289+ ''
1290+ ].join('\n')
1291+ ],
1292+ 'should work'
10441293 )
1294+ }
10451295
10461296 function clean() {
10471297 rimraf.sync('./.git')