-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 38ef2e1
Showing
10 changed files
with
343 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"plugins": [ | ||
"transform-es2015-classes", | ||
"transform-es2015-computed-properties", | ||
"transform-es2015-destructuring", | ||
"transform-es2015-for-of", | ||
"transform-es2015-function-name", | ||
"transform-es2015-literals", | ||
"transform-es2015-modules-commonjs", | ||
"transform-es2015-object-super", | ||
"transform-es2015-parameters", | ||
"transform-es2015-sticky-regex", | ||
"transform-es2015-typeof-symbol", | ||
"transform-es2015-unicode-regex", | ||
|
||
"transform-async-to-generator", | ||
"babel-plugin-espower" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"root": true, | ||
"parser": "babel-eslint", | ||
"extends": "airbnb/base" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.DS_Store | ||
node_modules | ||
lib |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
sudo: false | ||
language: node_js | ||
node_js: | ||
- 5 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
# textlint-rule-no-dead-link | ||
|
||
[![Build Status](https://travis-ci.org/nodaguti/textlint-rule-no-dead-link.svg?branch=master)](https://travis-ci.org/nodaguti/textlint-rule-no-dead-link) | ||
[![Dependency Status](https://david-dm.org/nodaguti/textlint-rule-no-dead-link.svg)](https://david-dm.org/nodaguti/textlint-rule-no-dead-link) | ||
[![devDependency Status](https://david-dm.org/nodaguti/textlint-rule-no-dead-link/dev-status.svg)](https://david-dm.org/nodaguti/textlint-rule-no-dead-link#info=devDependencies) | ||
|
||
[textlint](https://github.com/textlint/textlint) rule | ||
to check if all links are alive. | ||
|
||
This rule is mainly for Markdown documents, but it may also work for plain texts. | ||
|
||
## Installation | ||
``` | ||
$ npm install textlint-rule-no-dead-link | ||
``` | ||
|
||
## Usage | ||
``` | ||
$ npm install textlint textlint-rule-no-dead-link | ||
$ textlint --rule textlint-rule-no-dead-link text-to-check.txt | ||
``` | ||
|
||
## Options | ||
Write your configurations into `.textlintrc`. | ||
|
||
The default options are: | ||
``` | ||
{ | ||
"rules": { | ||
"no-dead-link": { | ||
"checkRelative": false, | ||
"baseURI": null, | ||
"ignore": [], | ||
} | ||
} | ||
} | ||
``` | ||
|
||
### checkRelative | ||
Enable the dead link checks against relative URIs. | ||
Note that you also have to specify the `baseURI`. | ||
|
||
### baseURI | ||
The base URI to use for all relative URIs contained within a document. | ||
|
||
Example: | ||
``` | ||
{ | ||
"rules": { | ||
"no-dead-link": { | ||
"checkRelative": true, | ||
"baseURI": "http://example.com/" | ||
} | ||
} | ||
} | ||
``` | ||
|
||
### ignore | ||
URI strings to be ignored. | ||
|
||
Example: | ||
``` | ||
{ | ||
"rules": { | ||
"no-dead-link": { | ||
"ignore": [ | ||
"http://example.com/not-exist/index.html" | ||
] | ||
} | ||
} | ||
} | ||
``` | ||
|
||
## Tests | ||
``` | ||
npm test | ||
``` | ||
|
||
## Contribution | ||
|
||
1. Fork it! | ||
2. Create your feature branch: `git checkout -b my-new-feature` | ||
3. Commit your changes: `git commit -am 'Add some feature'` | ||
4. Push to the branch: `git push origin my-new-feature` | ||
5. Submit a pull request :D | ||
|
||
## License | ||
|
||
MIT License (http://nodaguti.mit-license.org/) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
{ | ||
"name": "textlint-rule-no-dead-link", | ||
"version": "0.1.0", | ||
"description": "A textlint rule to check if all links are alive", | ||
"main": "lib/no-dead-link.js", | ||
"scripts": { | ||
"build": "babel src -d lib --source-maps", | ||
"prepublish": "npm run --if-present build", | ||
"test": "npm-run-all lint mocha", | ||
"lint": "eslint src test", | ||
"mocha": "mocha" | ||
}, | ||
"files": [ | ||
"lib", | ||
"src" | ||
], | ||
"keywords": [ | ||
"textlint", | ||
"rule" | ||
], | ||
"author": "nodaguti", | ||
"license": "MIT", | ||
"bugs": "https://github.com/nodaguti/textlint-rule-no-dead-link/issues", | ||
"homepage": "https://github.com/nodaguti/textlint-rule-no-dead-link", | ||
"repository": "nodaguti/textlint-rule-no-dead-link", | ||
"dependencies": { | ||
"isomorphic-fetch": "^2.2.1", | ||
"npm-run-all": "^1.5.3", | ||
"textlint-rule-helper": "^1.1.5" | ||
}, | ||
"devDependencies": { | ||
"babel-cli": "^6.6.5", | ||
"babel-core": "^6.7.2", | ||
"babel-eslint": "^5.0.0", | ||
"babel-plugin-espower": "^2.1.2", | ||
"babel-plugin-transform-async-to-generator": "^6.7.0", | ||
"babel-preset-es2015": "^6.6.0", | ||
"eslint": "~2.2.0", | ||
"eslint-config-airbnb": "^6.1.0", | ||
"mocha": "^2.4.5", | ||
"power-assert": "^1.3.1", | ||
"textlint": "^5.7.0", | ||
"textlint-tester": "^1.0.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import { RuleHelper } from 'textlint-rule-helper'; | ||
import fetch from 'isomorphic-fetch'; | ||
import URL from 'url'; | ||
|
||
const DEFAULT_OPTIONS = { | ||
checkRelative: false, | ||
baseURI: null, | ||
ignore: [], | ||
}; | ||
|
||
// http://stackoverflow.com/a/3809435/951517 | ||
// eslint-disable-next-line max-len | ||
const URI_REGEXP = /(https?:)?\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g; | ||
|
||
function isRelative(uri) { | ||
return URL.parse(uri).protocol === null; | ||
} | ||
|
||
async function isAlive(uri) { | ||
try { | ||
const res = await fetch(uri, { | ||
method: 'HEAD', | ||
}); | ||
return { | ||
ok: res.ok, | ||
message: `${res.status} ${res.statusText}`, | ||
}; | ||
} catch (err) { | ||
return { | ||
ok: false, | ||
message: err.message, | ||
}; | ||
} | ||
} | ||
|
||
function reporter(context, options = {}) { | ||
const { | ||
Syntax, | ||
getSource, | ||
report, | ||
RuleError, | ||
} = context; | ||
const helper = new RuleHelper(context); | ||
const opts = Object.assign({}, DEFAULT_OPTIONS, options); | ||
|
||
const lint = async (node, uri) => { | ||
if (opts.ignore.indexOf(uri) !== -1) { | ||
return; | ||
} | ||
|
||
if (isRelative(uri)) { | ||
if (!opts.checkRelative) { | ||
return; | ||
} | ||
|
||
if (!opts.baseURI) { | ||
const message = 'The base URI is not specified.'; | ||
report(node, new RuleError(message, { index: 0 })); | ||
return; | ||
} | ||
|
||
// eslint-disable-next-line no-param-reassign | ||
uri = URL.resolve(opts.baseURI, uri); | ||
} | ||
|
||
const { ok, message: msg } = await isAlive(uri); | ||
|
||
if (!ok) { | ||
const message = `${uri} is dead. (${msg})`; | ||
report(node, new RuleError(message, { index: 0 })); | ||
} | ||
}; | ||
|
||
return { | ||
[Syntax.Str](node) { | ||
if (helper.isChildNode(node, [Syntax.BlockQuote])) { | ||
return null; | ||
} | ||
|
||
// prevent double checks | ||
if (helper.isChildNode(node, [Syntax.Link])) { | ||
return null; | ||
} | ||
|
||
return (async () => { | ||
const text = getSource(node); | ||
const uris = text.match(URI_REGEXP); | ||
|
||
if (!uris) { | ||
return; | ||
} | ||
|
||
for (const uri of uris) { | ||
await lint(node, uri); | ||
} | ||
})(); | ||
}, | ||
|
||
[Syntax.Link](node) { | ||
if (helper.isChildNode(node, [Syntax.BlockQuote])) { | ||
return null; | ||
} | ||
|
||
return lint(node, node.url); | ||
}, | ||
}; | ||
} | ||
|
||
export default { | ||
linter: reporter, | ||
fixer: reporter, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"env": { | ||
"mocha": true | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
--compilers js:babel-core/register | ||
--timeout 10000 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import rule from '../src/no-dead-link'; | ||
import TextlintTester from 'textlint-tester'; | ||
|
||
const tester = new TextlintTester(); | ||
|
||
tester.run('no-dead-link', rule, { | ||
valid: [ | ||
'Normal URI: http://example.com/', | ||
'Normal link: [example](http://example.com)', | ||
{ | ||
text: 'Options: relative link: ![robot](/images/errors/robot.gif)', | ||
options: { | ||
checkRelative: true, | ||
baseURI: 'https://www.google.com/', | ||
}, | ||
}, | ||
{ | ||
text: 'Options: ignore: http://example.com/404', | ||
options: { | ||
ignore: ['http://example.com/404'], | ||
}, | ||
}, | ||
], | ||
invalid: [ | ||
{ | ||
text: '404 URI: http://example.com/404', | ||
errors: [ | ||
{ | ||
message: 'http://example.com/404 is dead. (404 Not Found)', | ||
line: 1, | ||
column: 10, | ||
}, | ||
], | ||
}, | ||
{ | ||
text: '404 link: [404](http://example.com/404)', | ||
errors: [ | ||
{ | ||
message: 'http://example.com/404 is dead. (404 Not Found)', | ||
line: 1, | ||
column: 11, | ||
}, | ||
], | ||
}, | ||
{ | ||
text: 'No base URI for relative URI: [no base](index.html)', | ||
options: { | ||
checkRelative: true, | ||
}, | ||
errors: [ | ||
{ | ||
message: 'The base URI is not specified.', | ||
line: 1, | ||
column: 31, | ||
}, | ||
], | ||
}, | ||
], | ||
}); |