Skip to content

Commit

Permalink
fix(plugin): Add url property to Link Node (#8)
Browse files Browse the repository at this point in the history
* Add url property to Link Node

When applying `textlint-rule-no-dead-link` to HTML, an error occurred.

`` `console
✖ Stack trace
TypeError: Parameter "url" must be a string, not undefined
    at Url.parse (url.js: 102: 11)
    at Object.urlParse [as parse] (url.js: 96: 5)
    at isRelative
(/usr/local/lib/node_modules/textlint-rule-no-dead-link/lib/no-dead-link
.js:83:24)
    at
/usr/local/lib/node_modules/textlint-rule-no-dead-link/lib/no-dead-link.
js: 107: 11
    at Generator.next (<anonymous>)
`` `

textlint-rule-no-dead-link expects the Link Node to hold the url
property, and in the case of txt, markdown it holds the actual url
property.
I think that the Link Node generated from the html file should also
keep the url property. [^ 1]

[1]: The href attribute of `a` tag is not mandatory.
If href does not exist, url is not set.
If url does not exist, a fix to ignore the target Link node is required
for `textlint-rule-no-dead-link`.

* Fix undefined check of href, and add test for placeholder.

Fix undefined check of href, and add test for placeholder.
  • Loading branch information
kemsakurai authored and azu committed Nov 19, 2017
1 parent 61db8c6 commit 5736b2a
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 7 deletions.
4 changes: 4 additions & 0 deletions src/html-to-ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ export function parse(html) {
node.range = range;
node.raw = html.slice(range[0], range[1]);
}
// map `url` to Link node
if (node.type === "Link" && typeof node.properties.href !== "undefined") {
node.url = node.properties.href;
}
}
removeUnusedProperties(node);
});
Expand Down
4 changes: 4 additions & 0 deletions test/ast-test-case/element-attributes/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,7 @@
<!--numeric:-->

<meter min="0" low="40" high="90" max="100" value="95"></meter>

<!--placeholder:-->

<a>placeholder</a>
113 changes: 106 additions & 7 deletions test/ast-test-case/element-attributes/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
{
"type": "Link",
"tagName": "a",
"url": "http://alpha.com",
"properties": {
"href": "http://alpha.com",
"className": [
Expand Down Expand Up @@ -2136,22 +2137,120 @@
},
{
"type": "Str",
"value": "\n",
"value": "\n\n",
"loc": {
"start": {
"line": 95,
"column": 63
},
"end": {
"line": 96,
"line": 97,
"column": 0
}
},
"range": [
1405,
1406
1407
],
"raw": "\n"
"raw": "\n\n"
},
{
"loc": {
"end": {
"column": 19,
"line": 97
},
"start": {
"column": 0,
"line": 97
}
},
"range": [
1407,
1426
],
"raw": "<!--placeholder:-->",
"type": "Comment",
"value": "placeholder:"
},
{
"loc": {
"end": {
"column": 0,
"line": 99
},
"start": {
"column": 19,
"line": 97
}
},
"range": [
1426,
1428
],
"raw": "\n\n",
"type": "Str",
"value": "\n\n"
},
{
"children": [
{
"loc": {
"end": {
"column": 14,
"line": 99
},
"start": {
"column": 3,
"line": 99
}
},
"range": [
1431,
1442
],
"raw": "placeholder",
"type": "Str",
"value": "placeholder"
}
],
"loc": {
"end": {
"column": 18,
"line": 99
},
"start": {
"column": 0,
"line": 99
}
},
"properties": {},
"range": [
1428,
1446
],
"raw": "<a>placeholder</a>",
"tagName": "a",
"type": "Link"
},
{
"loc": {
"end": {
"column": 0,
"line": 100
},
"start": {
"column": 18,
"line": 99
}
},
"range": [
1446,
1447
],
"raw": "\n",
"type": "Str",
"value": "\n"
}
],
"loc": {
Expand All @@ -2160,13 +2259,13 @@
"column": 0
},
"end": {
"line": 96,
"line": 100,
"column": 0
}
},
"range": [
0,
1406
1447
],
"raw": "<!--core:-->\n\n<a href=\"http://alpha.com\" class=\"bravo\" download></a>\n\n<!--double:-->\n\n<div class class></div>\n\n<!--unknown:-->\n\n<a ng-init></a>\n\n<a ng-repeat=\"\"></a>\n\n<a ng-click=\"ctrl.onintentclick($scope)\">ng-whatevs</a>.\n\n<!--empty:-->\n\n<abbr title></abbr>\n\n<!--space separated:-->\n\n<code class=\"language-foo bar\"></code>\n\n<code class=\"\"></code>\n\n<code class></code>\n\n<code class=\" \"></code>\n\n<!--comma separated:-->\n\n<img srcset=\"medium.jpg 1000w, large.jpg 2000w\">\n\n<img srcset=\"medium.jpg 1000w\">\n\n<img srcset=\"\">\n\n<img srcset=\" \">\n\n<img srcset=\",\">\n\n<img srcset=\" , \">\n\n<img srcset=\",foo\">\n\n<img srcset=\"bar,\">\n\n<img srcset=\",baz,\">\n\n<!--style:-->\n\n<div></div>\n\n<div style=\"\"></div>\n\n<div style=\"color\"></div>\n\n<div style=\"color:\"></div>\n\n<div style=\"color:red\"></div>\n\n<div style=\"color:;\"></div>\n\n<div style=\"color:red;\"></div>\n\n<div style=\"color:red;background-color\"></div>\n\n<div style=\"color:red;background-color: blue\"></div>\n\n<div style=\"color:red;background-color: blue;\"></div>\n\n<!--boolean:-->\n\n<script async></script>\n<script async=\"\"></script>\n<script async=\"async\"></script>\n\n<!--overloaded boolean (as boolean):-->\n\n<a download></a>\n<a download=\"\"></a>\n<a download=\"download\"></a>\n\n<!--overloaded boolean (as overloaded):-->\n\n<a download=\"example.mp3\"></a>\n\n<!--positive numeric:-->\n\n<img height=\"100\">\n\n<!--numeric:-->\n\n<meter min=\"0\" low=\"40\" high=\"90\" max=\"100\" value=\"95\"></meter>\n"
"raw": "<!--core:-->\n\n<a href=\"http://alpha.com\" class=\"bravo\" download></a>\n\n<!--double:-->\n\n<div class class></div>\n\n<!--unknown:-->\n\n<a ng-init></a>\n\n<a ng-repeat=\"\"></a>\n\n<a ng-click=\"ctrl.onintentclick($scope)\">ng-whatevs</a>.\n\n<!--empty:-->\n\n<abbr title></abbr>\n\n<!--space separated:-->\n\n<code class=\"language-foo bar\"></code>\n\n<code class=\"\"></code>\n\n<code class></code>\n\n<code class=\" \"></code>\n\n<!--comma separated:-->\n\n<img srcset=\"medium.jpg 1000w, large.jpg 2000w\">\n\n<img srcset=\"medium.jpg 1000w\">\n\n<img srcset=\"\">\n\n<img srcset=\" \">\n\n<img srcset=\",\">\n\n<img srcset=\" , \">\n\n<img srcset=\",foo\">\n\n<img srcset=\"bar,\">\n\n<img srcset=\",baz,\">\n\n<!--style:-->\n\n<div></div>\n\n<div style=\"\"></div>\n\n<div style=\"color\"></div>\n\n<div style=\"color:\"></div>\n\n<div style=\"color:red\"></div>\n\n<div style=\"color:;\"></div>\n\n<div style=\"color:red;\"></div>\n\n<div style=\"color:red;background-color\"></div>\n\n<div style=\"color:red;background-color: blue\"></div>\n\n<div style=\"color:red;background-color: blue;\"></div>\n\n<!--boolean:-->\n\n<script async></script>\n<script async=\"\"></script>\n<script async=\"async\"></script>\n\n<!--overloaded boolean (as boolean):-->\n\n<a download></a>\n<a download=\"\"></a>\n<a download=\"download\"></a>\n\n<!--overloaded boolean (as overloaded):-->\n\n<a download=\"example.mp3\"></a>\n\n<!--positive numeric:-->\n\n<img height=\"100\">\n\n<!--numeric:-->\n\n<meter min=\"0\" low=\"40\" high=\"90\" max=\"100\" value=\"95\"></meter>\n\n<!--placeholder:-->\n\n<a>placeholder</a>\n"
}

0 comments on commit 5736b2a

Please sign in to comment.