Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add helper.isPlainStrNode methods #17

Merged
merged 6 commits into from
May 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: test
on: [push, pull_request]
jobs:
test:
name: "Test on Node.js ${{ matrix.node-version }}"
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12, 14]
steps:
- name: checkout
uses: actions/checkout@v2
- name: setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- name: Install
run: yarn install
- name: Test
run: yarn test
5 changes: 5 additions & 0 deletions .mocharc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"require": [
"ts-node-test-register"
]
}
4 changes: 0 additions & 4 deletions .travis.yml

This file was deleted.

42 changes: 41 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# textlint-rule-helper [![Build Status](https://travis-ci.org/textlint/textlint-rule-helper.svg?branch=master)](https://travis-ci.org/textlint/textlint-rule-helper)
# textlint-rule-helper [![Actions Status: test](https://github.com/textlint/textlint-rule-helper/workflows/test/badge.svg)](https://github.com/textlint/textlint-rule-helper/actions?query=workflow%3A"test")

This is helper library for creating [textlint](https://github.com/textlint/textlint "textlint") rule.

Expand Down Expand Up @@ -33,6 +33,46 @@ Return true if `node` is wrapped any one of node `types`.
- node `TxtNode` - is target node
- types `Array.<string>` - are wrapped target node

#### ruleHelper.isPlainStrNode(node): boolean

Return true if the node is Str node and fill following conditions:

- the node is Str node
- the node is under the Paragraph node
- the node is not under the BlockQuote

This function is useful for common use-case.
If you want to lint Str node, but you not want to lint styled node, this function is useful.
The styled node is Link, Strong, BlockQuote, Header etc, and it may be written by another people.
For example, you have added a link to your document, the link's title is written by another people.

Opposite of it, The plain Str node is just under the Paragraph node, and it was written by user.

**Examples**

Return true

```markdown
str str str
- list text
```

Return false

```markdown
# Header
![alt text](https://example.com)
[link title](https://example.com)
> BlockQuote text
**Strong text**
[linkReference][]
[^footnote text]
```

**Params**

- node `TxtNode` - is target node

### class IgnoreNodeManager

You can manager ignoring range in texts.
Expand Down
22 changes: 11 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "textlint-rule-helper",
"version": "2.1.1",
"description": "Helper for textlint rule.",
"description": "A helper library for textlint rule.",
"homepage": "https://github.com/textlint/textlint-rule-helper/",
"bugs": {
"url": "https://github.com/textlint/textlint-rule-helper/issues"
Expand All @@ -25,22 +25,22 @@
"watch": "tsc -p . --watch"
},
"dependencies": {
"@textlint/ast-node-types": "^4.2.1",
"@textlint/types": "^1.1.2",
"@textlint/ast-node-types": "^4.4.3",
"@textlint/types": "^1.5.5",
"structured-source": "^3.0.2",
"unist-util-visit": "^1.1.0"
},
"devDependencies": {
"@types/mocha": "^5.2.5",
"@types/node": "^10.12.18",
"@types/mocha": "^8.2.2",
"@types/node": "^15.3.0",
"@types/structured-source": "^3.0.0",
"cross-env": "^5.2.0",
"cross-env": "^7.0.3",
"markdown-to-ast": "^6.0.3",
"mocha": "^5.2.0",
"textlint": "^11.2.1",
"ts-node": "^7.0.1",
"ts-node-test-register": "^4.0.0",
"mocha": "^8.4.0",
"textlint": "^11.9.1",
"ts-node": "^9.1.1",
"ts-node-test-register": "^9.0.1",
"txt-ast-traverse": "^2.0.4",
"typescript": "^3.2.2"
"typescript": "^4.2.4"
}
}
63 changes: 59 additions & 4 deletions src/textlint-rule-helper.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { TxtNode } from "@textlint/ast-node-types"
import { TextlintRuleContext } from "@textlint/types"
import { ASTNodeTypes, TxtNode } from "@textlint/ast-node-types"

/**
* RuleHelper is helper class for textlint.
* @class RuleHelper
*/
export default class RuleHelper {
// @ts-ignore
private _ruleContext: any;
private _ruleContext: Readonly<TextlintRuleContext>;

/**
* Initialize RuleHelper with RuleContext object.
* @param {RuleContext} ruleContext the ruleContext is context object of the rule.
* @param ruleContext the ruleContext is context object of the rule.
*/
constructor(ruleContext: any) {
constructor(ruleContext: Readonly<TextlintRuleContext>) {
this._ruleContext = ruleContext;
}

Expand Down Expand Up @@ -49,4 +50,58 @@ export default class RuleHelper {
});
});
}

/**
* Return true if the node is Str node and fill following conditions
*
* - the node is Str node
* - the node is under the Paragraph node
* - the node is not under the BlockQuote
*
* This function is useful for common use-case.
* If you want to lint Str node, but you not want to lint styled node, this function is useful.
* styled node is Link, Strong, BlockQuote, Header etc...
* Opposite of it, plain str node is just under the Paragraph node.
*
* @example
*
* Return true
*
* ---
* str str str
* - list text
* ---
*
* Return false
*
* ----
* # Header
* ![alt text](https://example.com)
* [link title](https://example.com)
* > BlockQuote
* **Strong**
* [^footnote]: text text
* ----
*
* Summary:
*
* Return true if the node is plain text.
* In other words, return false if the node is styled
*
* @param node
*/
isPlainStrNode(node: TxtNode): boolean {
if (node.type !== ASTNodeTypes.Str) {
return false;
}
if (node.parent?.type !== ASTNodeTypes.Paragraph) {
return false;
}

const isInUncontrollableNode = this.isChildNode(node, [
// <blockquote> is Block node in html. It can has Pragaraph node as children
ASTNodeTypes.BlockQuote
]);
return !isInUncontrollableNode
}
}
2 changes: 2 additions & 0 deletions src/wrap-report-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export function wrapReportHandler<T extends Readonly<TextlintRuleContext>, R ext
const ignoreNodeTypes = options.ignoreNodeTypes || [];
const ignoreNodeManager = new IgnoreNodeManager();
const ruleHelper = new RuleHelper(context);
// @ts-expect-error: https://github.com/textlint/textlint/issues/770
const text = context.getSource();
const sourceLocation = new SourceLocation(text);
const reportIfUnignored = function reportIfUnignored(node: AnyTxtNode, ruleError: TextlintRuleError): void | Promise<any> {
Expand All @@ -54,6 +55,7 @@ export function wrapReportHandler<T extends Readonly<TextlintRuleContext>, R ext
}
return nodeHandler(node);
};
// @ts-expect-error: ignore
handlers[nodeType] = wrappedNodeHandler
});
return handlers;
Expand Down
1 change: 0 additions & 1 deletion test/mocha.opts

This file was deleted.

71 changes: 71 additions & 0 deletions test/textlint-rule-helper-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,75 @@ describe("textlint-rule-helper-test", function () {
});
});
});
describe("#isPlainStrNode(node)", () => {
it("should return true if the node is under the paragraph", () => {
const text = "text";
let result: boolean;
textlint.setupRules({
"rule-key": function (context: any) {
const helper = new RuleHelper(context);
return {
[context.Syntax.Str](node: TxtNode) {
result = helper.isPlainStrNode(node)
}
}
}
});
return textlint.lintMarkdown(text).then(() => {
assert.ok(result);
});
});
it("should return true if the node is under the paragraph in list", () => {
const text = "- text";
let result: boolean;
textlint.setupRules({
"rule-key": function (context: any) {
const helper = new RuleHelper(context);
return {
[context.Syntax.Str](node: TxtNode) {
result = helper.isPlainStrNode(node)
}
}
}
});
return textlint.lintMarkdown(text).then(() => {
assert.ok(result);
});
});
it("should return false if the node is under the Img, Link, Header, Strong", () => {
const text = `# text
![text](https://example.com/img)[text](https://example.com/img)**strong**__strong__`;
const results: boolean[] = [];
textlint.setupRules({
"rule-key": function (context: any) {
const helper = new RuleHelper(context);
return {
[context.Syntax.Str](node: TxtNode) {
results.push(helper.isPlainStrNode(node))
}
}
}
});
return textlint.lintMarkdown(text).then(() => {
results.forEach(result => assert(!result))
});
})
it("should return false if the node is under the blockquote ", () => {
const text = "> text";
let result: boolean;
textlint.setupRules({
"rule-key": function (context: any) {
const helper = new RuleHelper(context);
return {
[context.Syntax.Str](node: TxtNode) {
result = helper.isPlainStrNode(node)
}
}
}
});
return textlint.lintMarkdown(text).then(() => {
assert.ok(!result);
});
})
})
});
Loading