Skip to content

Commit 2d49761

Browse files
committed
Add skipPathPatterns
Closes GH-18.
1 parent fee7cfa commit 2d49761

File tree

3 files changed

+61
-2
lines changed

3 files changed

+61
-2
lines changed

lib/index.js

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@
2424
* Path to Git root folder (default: local Git folder);
2525
* if both `root` and `repository` are nullish, the Git root is detected;
2626
* if `root` is not given but `repository` is, `file.cwd` is used.
27+
* @property {ReadonlyArray<RegExp | string> | null | undefined} [skipPathPatterns]
28+
* List of patterns for *paths* that should be skipped;
29+
* each absolute local path + hash will be tested against each pattern and
30+
* will be ignored if `new RegExp(pattern).test(value) === true`;
31+
* example value are then `/Users/tilde/path/to/repo/readme.md#some-heading`.
2732
* @property {Readonly<UrlConfig> | null | undefined} [urlConfig]
2833
* Config on how hosted Git works (default: detected from repo);
2934
* `github.com`, `gitlab.com`, or `bitbucket.org` work automatically;
@@ -79,6 +84,8 @@
7984
* Path to file.
8085
* @property {string | null | undefined} root
8186
* Path to Git folder.
87+
* @property {ReadonlyArray<RegExp>} skipPathPatterns
88+
* List of patterns for paths that should be skipped.
8289
* @property {Readonly<UrlConfig>} urlConfig
8390
* Configuration.
8491
*/
@@ -195,6 +202,11 @@ const readmeBasename = /^readme$/i
195202
*/
196203
export default function remarkValidateLinks(options, fileSet) {
197204
const settings = options || {}
205+
const skipPathPatterns = settings.skipPathPatterns
206+
? settings.skipPathPatterns.map(function (d) {
207+
return typeof d === 'string' ? new RegExp(d) : d
208+
})
209+
: []
198210

199211
// Attach a `completer`.
200212
if (fileSet) {
@@ -270,6 +282,7 @@ export default function remarkValidateLinks(options, fileSet) {
270282
base: absolute ? path.dirname(absolute) : file.cwd,
271283
path: absolute,
272284
root,
285+
skipPathPatterns,
273286
urlConfig
274287
}
275288
/** @type {Set<string>} */
@@ -310,6 +323,15 @@ export default function remarkValidateLinks(options, fileSet) {
310323
if (info) {
311324
const fp = info.filePath
312325
const hash = info.hash
326+
const together = fp + (hash ? '#' + hash : '')
327+
328+
if (
329+
state.skipPathPatterns.some(function (skipPattern) {
330+
return skipPattern.test(together)
331+
})
332+
) {
333+
return
334+
}
313335

314336
addReference(fp, '', node)
315337

@@ -556,12 +578,14 @@ async function checkAll(files) {
556578
* Landmarks.
557579
* @param {ReferenceInfo} reference
558580
* Reference.
581+
* @returns {undefined}
582+
* Nothing.
559583
*/
560584
function warn(landmarks, reference) {
561585
const absolute = reference.file.path
562586
? path.resolve(reference.file.cwd, reference.file.path)
563587
: ''
564-
const base = absolute ? path.dirname(absolute) : null
588+
const base = absolute ? path.dirname(absolute) : undefined
565589
const filePath = base
566590
? path.relative(base, reference.reference.filePath)
567591
: reference.reference.filePath

readme.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,12 @@ Configuration (TypeScript type).
192192
the Git root is detected;
193193
if `root` is not given but `repository` is,
194194
`file.cwd` is used
195+
* `skipPathPatterns`
196+
(`Array<RegExp | string>`, optional)
197+
— list of patterns for *paths* that should be skipped;
198+
each absolute local path + hash will be tested against each pattern and
199+
will be ignored if `new RegExp(pattern).test(value) === true`;
200+
example value are then `/Users/tilde/path/to/repo/readme.md#some-heading`.
195201
* `urlConfig`
196202
([`UrlConfig`][api-url-config], default: detected from repo)
197203
— config on how hosted Git works;

test/index.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import remarkValidateLinks from 'remark-validate-links'
1919
import {remark} from 'remark'
2020
import stripAnsi from 'strip-ansi'
2121
import {read} from 'to-vfile'
22+
import {VFile} from 'vfile'
2223
import sort from './sort.js'
2324

2425
const exec = promisify(execCallback)
@@ -93,6 +94,34 @@ test('remark-validate-links', async function (t) {
9394
assert.deepEqual(file.messages.map(String), [])
9495
})
9596

97+
await t.test('should support `skipUrlPatterns` (1)', async function () {
98+
const file = await remark()
99+
.use(remarkValidateLinks, {skipPathPatterns: ['#e']})
100+
.use(sort)
101+
.process('a [b](#c) [d](#e) f')
102+
103+
assert.deepEqual(file.messages.map(String), [
104+
'1:3-1:10: Cannot find heading for `#c`'
105+
])
106+
})
107+
108+
await t.test('should support `skipUrlPatterns` (2)', async function () {
109+
const file = new VFile({
110+
cwd: fileURLToPath(fakeBaseUrl),
111+
path: 'example.md',
112+
value: 'a [b](../../new/main/?filename=skeets/<your-path>.tweet) c'
113+
})
114+
115+
await remark()
116+
.use(remarkValidateLinks, {
117+
skipPathPatterns: [/remark-validate-links[/\\]new[/\\]/]
118+
})
119+
.use(sort)
120+
.process(file)
121+
122+
assert.deepEqual(file.messages.map(String), [])
123+
})
124+
96125
await t.test('should ignore invalid repositories', async function () {
97126
const result = await exec(
98127
[
@@ -1128,7 +1157,7 @@ test('remark-validate-links', async function (t) {
11281157
* @returns {string}
11291158
* Clean error.
11301159
*/
1131-
export function cleanError(value, max) {
1160+
function cleanError(value, max) {
11321161
return (
11331162
value
11341163
// Clean syscal errors

0 commit comments

Comments
 (0)