Add MD049/emphasis-style (fixes #150).

This commit is contained in:
Sébastien Règne 2021-10-24 06:54:58 +02:00 committed by GitHub
parent aa8aa83db8
commit 39724b991a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 418 additions and 35 deletions

View file

@ -102,6 +102,7 @@ playground for learning and exploring.
* **[MD046](doc/Rules.md#md046)** *code-block-style* - Code block style
* **[MD047](doc/Rules.md#md047)** *single-trailing-newline* - Files should end with a single newline character
* **[MD048](doc/Rules.md#md048)** *code-fence-style* - Code fence style
* **[MD049](doc/Rules.md#md049)** *emphasis-style* - Emphasis style should be consistent
* **[MD050](doc/Rules.md#md050)** *strong-style* - Strong style should be consistent
<!-- markdownlint-restore -->
@ -126,7 +127,7 @@ rules at once.
* **blockquote** - MD027, MD028
* **bullet** - MD004, MD005, MD006, MD007, MD032
* **code** - MD014, MD031, MD038, MD040, MD046, MD048
* **emphasis** - MD036, MD037, MD050
* **emphasis** - MD036, MD037, MD049, MD050
* **hard_tab** - MD010
* **headers** - MD001, MD002, MD003, MD018, MD019, MD020, MD021, MD022,
MD023, MD024, MD025, MD026, MD036, MD041, MD043

View file

@ -4039,6 +4039,36 @@ module.exports = {
};
/***/ }),
/***/ "../lib/md049.js":
/*!***********************!*\
!*** ../lib/md049.js ***!
\***********************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
// @ts-check
var _a = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"), addErrorDetailIf = _a.addErrorDetailIf, emphasisOrStrongStyleFor = _a.emphasisOrStrongStyleFor, forEachInlineChild = _a.forEachInlineChild;
module.exports = {
"names": ["MD049", "emphasis-style"],
"description": "Emphasis style should be consistent",
"tags": ["emphasis"],
"function": function MD049(params, onError) {
var expectedStyle = String(params.config.style || "consistent");
forEachInlineChild(params, "em_open", function (token) {
var lineNumber = token.lineNumber, markup = token.markup;
var markupStyle = emphasisOrStrongStyleFor(markup);
if (expectedStyle === "consistent") {
expectedStyle = markupStyle;
}
addErrorDetailIf(onError, lineNumber, expectedStyle, markupStyle);
});
}
};
/***/ }),
/***/ "../lib/md050.js":
@ -4128,6 +4158,7 @@ var rules = [
__webpack_require__(/*! ./md046 */ "../lib/md046.js"),
__webpack_require__(/*! ./md047 */ "../lib/md047.js"),
__webpack_require__(/*! ./md048 */ "../lib/md048.js"),
__webpack_require__(/*! ./md049 */ "../lib/md049.js"),
__webpack_require__(/*! ./md050 */ "../lib/md050.js")
];
rules.forEach(function (rule) {

View file

@ -1331,20 +1331,20 @@ For more information, see <https://www.example.com/>.
```
Note: To use a bare URL without it being converted into a link, enclose it in
a code block, otherwise in some markdown parsers it _will_ be converted:
a code block, otherwise in some markdown parsers it *will* be converted:
```markdown
`https://www.example.com`
```
Note: The following scenario does _not_ trigger this rule to avoid conflicts
Note: The following scenario does *not* trigger this rule to avoid conflicts
with `MD011`/`no-reversed-links`:
```markdown
[https://www.example.com]
```
The use of quotes around a bare link will _not_ trigger this rule, either:
The use of quotes around a bare link will *not* trigger this rule, either:
```markdown
"https://www.example.com"
@ -1912,6 +1912,36 @@ can require that usage be consistent within the document.
Rationale: Consistent formatting makes it easier to understand a document.
<a name="md049"></a>
## MD049 - Emphasis style should be consistent
Tags: emphasis
Aliases: emphasis-style
Parameters: style ("consistent", "asterisk", "underscore"; default "consistent")
This rule is triggered when the symbols used in the document for emphasis do not
match the configured emphasis style:
```markdown
*Text*
_Text_
```
To fix this issue, use the configured emphasis style throughout the document:
```markdown
*Text*
*Text*
```
The configured emphasis style can be a specific symbol to use ("asterisk",
"underscore"), or can require that usage be consistent within the document.
Rationale: Consistent formatting makes it easier to understand a document.
<a name="md050"></a>
## MD050 - Strong style should be consistent

28
lib/md049.js Normal file
View file

@ -0,0 +1,28 @@
// @ts-check
"use strict";
const { addErrorDetailIf, emphasisOrStrongStyleFor, forEachInlineChild } =
require("../helpers");
module.exports = {
"names": [ "MD049", "emphasis-style" ],
"description": "Emphasis style should be consistent",
"tags": [ "emphasis" ],
"function": function MD049(params, onError) {
let expectedStyle = String(params.config.style || "consistent");
forEachInlineChild(params, "em_open", (token) => {
const { lineNumber, markup } = token;
const markupStyle = emphasisOrStrongStyleFor(markup);
if (expectedStyle === "consistent") {
expectedStyle = markupStyle;
}
addErrorDetailIf(
onError,
lineNumber,
expectedStyle,
markupStyle
);
});
}
};

View file

@ -51,6 +51,7 @@ const rules = [
require("./md046"),
require("./md047"),
require("./md048"),
require("./md049"),
require("./md050")
];
rules.forEach((rule) => {

View file

@ -250,6 +250,12 @@
"style": "consistent"
},
// MD049/emphasis-style - Emphasis style should be consistent
"MD049": {
// Emphasis style should be consistent
"style": "consistent"
},
// MD050/strong-style - Strong style should be consistent
"MD050": {
// Strong style should be consistent

View file

@ -226,6 +226,11 @@ MD048:
# Code fence style
style: "consistent"
# MD049/emphasis-style - Emphasis style should be consistent
MD049:
# Emphasis style should be consistent
style: "consistent"
# MD050/strong-style - Strong style should be consistent
MD050:
# Strong style should be consistent

View file

@ -396,6 +396,20 @@ rules.forEach(function forRule(rule) {
}
};
break;
case "MD049":
scheme.properties = {
"style": {
"description": "Emphasis style should be consistent",
"type": "string",
"enum": [
"consistent",
"asterisk",
"underscore"
],
"default": "consistent"
}
};
break;
case "MD050":
scheme.properties = {
"style": {

View file

@ -1439,6 +1439,48 @@
},
"additionalProperties": false
},
"MD049": {
"description": "MD049/emphasis-style - Emphasis style should be consistent",
"type": [
"boolean",
"object"
],
"default": true,
"properties": {
"style": {
"description": "Emphasis style should be consistent",
"type": "string",
"enum": [
"consistent",
"asterisk",
"underscore"
],
"default": "consistent"
}
},
"additionalProperties": false
},
"emphasis-style": {
"description": "MD049/emphasis-style - Emphasis style should be consistent",
"type": [
"boolean",
"object"
],
"default": true,
"properties": {
"style": {
"description": "Emphasis style should be consistent",
"type": "string",
"enum": [
"consistent",
"asterisk",
"underscore"
],
"default": "consistent"
}
},
"additionalProperties": false
},
"MD050": {
"description": "MD050/strong-style - Strong style should be consistent",
"type": [
@ -1577,7 +1619,7 @@
"default": true
},
"emphasis": {
"description": "emphasis - MD036, MD037, MD050",
"description": "emphasis - MD036, MD037, MD049, MD050",
"type": "boolean",
"default": true
},

View file

@ -85,6 +85,10 @@ markdownLint {MD044}
![](image.jpg) {MD045}
## Heading 10 {MD022}
Emphasis _with_ underscore style
Emphasis *with* different style {MD049}
Strong __with__ underscore style
Strong **with** different style {MD050}

View file

@ -1,4 +1,5 @@
{
"default": true,
"MD041": false
"MD041": false,
"MD049": false
}

View file

@ -8,11 +8,11 @@ Text
Text
> *Text*
> *Text* {MD049}
Text
> *Text text text*
> *Text text text* {MD049}
Text

View file

@ -27,7 +27,7 @@ Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore
eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt
in culpa qui officia deserunt mollit anim id est laborum.
_Section 3: oh no more sections {MD036}_
_Section 3: oh no more sections {MD036} {MD049}_
This is a normal paragraph
**that just happens to have emphasized text in**

View file

@ -0,0 +1,6 @@
{
"default": true,
"MD049": {
"style": "asterisk"
}
}

View file

@ -0,0 +1,5 @@
# Emphasis style asterisk
This is *fine*
This is _not_ {MD049}

View file

@ -0,0 +1,6 @@
{
"default": true,
"MD049": {
"style": "underscore"
}
}

View file

@ -0,0 +1,5 @@
# Emphasis style underscore
This is _fine_
This is *not* {MD049}

View file

@ -2,9 +2,9 @@
[test _test_ test](www.test.com)
[test `test` test](www.test.com)
[test *test* test](www.test.com)
[test *test* *test* test](www.test.com)
[test *test* *test* *test* test](www.test.com)
[test *test* test](www.test.com) {MD049}
[test *test* *test* test](www.test.com) {MD049}
[test *test* *test* *test* test](www.test.com) {MD049}
[test **test** test](www.test.com)
[test __test__ test](www.test.com) {MD050}
[this should not raise](www.shouldnotraise.com)

View file

@ -10,7 +10,7 @@
[This link has `code` and right space ](link) {MD039}
[ This link has _emphasis_ and left space](link) {MD039}
[ This link has _emphasis_ and left space](link) {MD039} {MD049}
[This](link) line has [multiple](link) links.

View file

@ -32,15 +32,15 @@ This long line includes a simple [reference][label] link and is long enough to v
*[This long line is comprised of an emphasized link](https://example.com "This is the long link's title")*
_[This long line is comprised of an emphasized link](https://example.com "This is the long link's title")_
_[This long line is comprised of an emphasized link {MD049}](https://example.com "This is the long link's title")_
**[This long line is comprised of a bolded link](https://example.com "This is the long link's title")**
__[This long line is comprised of a bolded link {MD050}](https://example.com "This is the long link's title")__
_**[This long line is comprised of an emphasized and bolded link](https://example.com "This is the long link's title")**_
_**[This long line is comprised of an emphasized and bolded link {MD049}](https://example.com "This is the long link's title")**_
**_[This long line is comprised of an emphasized and bolded link](https://example.com "This is the long link's title")_**
**_[This long line is comprised of an emphasized and bolded link {MD049}](https://example.com "This is the long link's title")_**
*[](https://example.com "This long line is comprised of an emphasized link with empty text and a non-empty title")*

View file

@ -110,7 +110,12 @@ test("https://github.com/mochajs/mocha", (t) => {
test("https://github.com/pi-hole/docs", (t) => {
const rootDir = "./test-repos/pi-hole-docs";
const globPatterns = [ join(rootDir, "**/*.md") ];
const globPatterns = [
join(rootDir, "**/*.md"),
"!" + join(rootDir, "docs/guides/dns/unbound.md"),
"!" + join(rootDir, "docs/index.md"),
"!" + join(rootDir, "docs/main/prerequisites.md")
];
const configPath = join(rootDir, ".markdownlint.json");
return lintTestRepo(t, globPatterns, configPath);
});
@ -141,11 +146,188 @@ if (existsSync(dotnetDocsDir)) {
const globPatterns = [
join(rootDir, "**/*.md"),
"!" + join(rootDir, "samples/**/*.md"),
"!" + join(rootDir, "docs/architecture/cloud-native/candidate-apps.md"),
"!" + join(
rootDir,
"docs/architecture/containerized-lifecycle/docker-devops-workflow" +
"/docker-application-outer-loop-devops-workflow.md"
),
"!" + join(
rootDir,
"docs/architecture/dapr-for-net-developers/getting-started.md"
),
"!" + join(
rootDir,
"docs/architecture/grpc-for-wcf-developers/channel-credentials.md"
),
"!" + join(
rootDir,
"docs/architecture/microservices/implement-resilient-applications" +
"/use-httpclientfactory-to-implement-resilient-http-requests.md"
),
"!" + join(
rootDir,
"docs/architecture/microservices" +
"/multi-container-microservice-net-applications" +
"/implement-api-gateways-with-ocelot.md"
),
"!" + join(
rootDir,
"docs/architecture/modern-web-apps-azure/architectural-principles.md"
),
"!" + join(
rootDir,
"docs/architecture/modern-web-apps-azure" +
"/azure-hosting-recommendations-for-asp-net-web-apps.md"
),
"!" + join(
rootDir,
"docs/architecture/modern-web-apps-azure" +
"/common-client-side-web-technologies.md"
),
"!" + join(
rootDir,
"docs/architecture/modern-web-apps-azure" +
"/develop-asp-net-core-mvc-apps.md"
),
"!" + join(
rootDir,
"docs/architecture/modern-web-apps-azure" +
"/development-process-for-azure.md"
),
"!" + join(rootDir, "docs/architecture/modern-web-apps-azure/index.md"),
"!" + join(rootDir, "docs/core/additional-tools/dotnet-svcutil-guide.md"),
"!" + join(rootDir, "docs/core/dependency-loading/collect-details.md"),
"!" + join(rootDir, "docs/core/deploying/single-file.md"),
"!" + join(rootDir, "docs/core/deploying/trimming/trimming-options.md"),
"!" + join(rootDir, "docs/core/extensions/cloud-service.md"),
"!" + join(rootDir, "docs/core/extensions/console-log-formatter.md"),
"!" + join(rootDir, "docs/core/extensions/create-resource-files.md"),
"!" + join(rootDir, "docs/core/extensions/localization.md"),
"!" + join(rootDir, "docs/core/install/linux-alpine.md"),
"!" + join(rootDir, "docs/core/install/windows.md"),
"!" + join(rootDir, "docs/core/porting/third-party-deps.md"),
"!" + join(rootDir, "docs/core/project-sdk/msbuild-props-desktop.md"),
"!" + join(rootDir, "docs/core/testing/unit-testing-code-coverage.md"),
"!" + join(rootDir, "docs/core/tools/troubleshoot-usage-issues.md"),
"!" + join(
rootDir,
"docs/core/tutorials/cli-templates-create-item-template.md"
),
"!" + join(
rootDir,
"docs/core/tutorials/cli-templates-create-project-template.md"
),
"!" + join(
rootDir,
"docs/core/tutorials/cli-templates-create-template-pack.md"
),
"!" + join(
rootDir,
"docs/core/tutorials/cli-templates-create-item-template.md"
),
"!" + join(
rootDir,
"docs/core/tutorials/cli-templates-create-project-template.md"
),
"!" + join(
rootDir,
"docs/core/tutorials/cli-templates-create-template-pack.md"
),
"!" + join(rootDir, "docs/core/whats-new/dotnet-core-3-0.md"),
"!" + join(
rootDir,
"docs/csharp/language-reference/compiler-options/code-generation.md"
),
"!" + join(rootDir, "docs/csharp/linq/query-expression-basics.md"),
"!" + join(
rootDir,
"docs/csharp/programming-guide/classes-and-structs" +
"/named-and-optional-arguments.md"
),
"!" + join(
rootDir,
"docs/csharp/roslyn-sdk/tutorials" +
"/how-to-write-csharp-analyzer-code-fix.md"
),
"!" + join(rootDir, "docs/csharp/tutorials/attributes.md"),
"!" + join(rootDir, "docs/csharp/whats-new/csharp-version-history.md"),
"!" + join(
rootDir,
"docs/framework/data/adonet/dataset-datatable-dataview" +
"/security-guidance.md"
),
"!" + join(
rootDir,
"docs/fsharp/language-reference/compiler-directives.md"
),
"!" + join(
rootDir,
"docs/fsharp/language-reference/exception-handling" +
"/the-try-with-expression.md"
),
"!" + join(
rootDir,
"docs/fsharp/language-reference/xml-documentation.md"
),
"!" + join(rootDir, "docs/fsharp/style-guide/conventions.md"),
"!" + join(
rootDir,
"docs/fsharp/tutorials/asynchronous-and-concurrent-programming/async.md"
),
"!" + join(
rootDir,
"docs/fundamentals/code-analysis/configuration-files.md"
),
"!" + join(
rootDir,
"docs/fundamentals/code-analysis/style-rules/naming-rules.md"
),
"!" + join(
rootDir,
"docs/machine-learning/tutorials" +
"/health-violation-classification-model-builder.md"
),
"!" + join(
rootDir,
"docs/machine-learning/tutorials/object-detection-model-builder.md"
),
"!" + join(
rootDir,
"docs/machine-learning/tutorials/object-detection-onnx.md"
),
"!" + join(
rootDir,
"docs/machine-learning/tutorials/text-classification-tf.md"
),
"!" + join(
rootDir,
"docs/standard/asynchronous-programming-patterns" +
"/event-based-asynchronous-pattern-overview.md"
),
"!" + join(
rootDir,
"docs/standard/asynchronous-programming-patterns" +
"/implementing-the-event-based-asynchronous-pattern.md"
),
"!" + join(
rootDir,
"docs/standard/base-types/string-comparison-net-5-plus.md"
),
"!" + join(rootDir, "docs/standard/delegates-lambdas.md"),
"!" + join(rootDir, "docs/standard/io/isolated-storage.md"),
"!" + join(
rootDir,
"docs/standard/native-interop/tutorial-comwrappers.md"
),
"!" + join(
rootDir,
"docs/standard/serialization/xml-schema-definition-tool-xsd-exe.md"
),
"!" + join(
rootDir,
"docs/standard/serialization/xml-serializer-generator-tool-sgen-exe.md"
),
"!" + join(rootDir, "docs/standard/native-interop/best-practices.md"),
"!" + join(
rootDir,
@ -154,7 +336,7 @@ if (existsSync(dotnetDocsDir)) {
"!" + join(
rootDir,
"docs/framework/windows-workflow-foundation/authoring-workflows-" +
"activities-and-expressions-using-imperative-code.md"
"activities-and-expressions-using-imperative-code.md"
),
"!" + join(
rootDir,
@ -170,7 +352,21 @@ const v8v8DevDir = "./test-repos/v8-v8-dev";
if (existsSync(v8v8DevDir)) {
test("https://github.com/v8/v8.dev", (t) => {
const rootDir = v8v8DevDir;
const globPatterns = [ join(rootDir, "src/**/*.md") ];
const globPatterns = [
join(rootDir, "src/**/*.md"),
"!" + join(rootDir, "src/blog/array-sort.md"),
"!" + join(rootDir, "src/blog/code-caching-for-devs.md"),
"!" + join(rootDir, "src/blog/fast-async.md"),
"!" + join(rootDir, "src/blog/liftoff.md"),
"!" + join(rootDir, "src/blog/pointer-compression.md"),
"!" + join(rootDir, "src/blog/react-cliff.md"),
"!" + join(rootDir, "src/blog/slack-tracking.md"),
"!" + join(rootDir, "src/blog/v8-release-74.md"),
"!" + join(rootDir, "src/features/bigint.md"),
"!" + join(rootDir, "src/features/dynamic-import.md"),
"!" + join(rootDir, "src/features/globalthis.md"),
"!" + join(rootDir, "src/features/modules.md")
];
const configPath = join(rootDir, ".markdownlint.json");
return lintTestRepo(t, globPatterns, configPath);
});

View file

@ -492,9 +492,10 @@ test.cb("styleAll", (t) => {
"MD042": [ 81 ],
"MD045": [ 85 ],
"MD046": [ 49, 73, 77 ],
"MD047": [ 92 ],
"MD047": [ 96 ],
"MD048": [ 77 ],
"MD050": [ 90 ]
"MD049": [ 90 ],
"MD050": [ 94 ]
}
};
// @ts-ignore
@ -536,9 +537,10 @@ test.cb("styleRelaxed", (t) => {
"MD042": [ 81 ],
"MD045": [ 85 ],
"MD046": [ 49, 73, 77 ],
"MD047": [ 92 ],
"MD047": [ 96 ],
"MD048": [ 77 ],
"MD050": [ 90 ]
"MD049": [ 90 ],
"MD050": [ 94 ]
}
};
// @ts-ignore
@ -839,7 +841,7 @@ test.cb("customFileSystemAsync", (t) => {
});
});
test.cb("readme", (t) => {
t.plan(117);
t.plan(119);
const tagToRules = {};
rules.forEach(function forRule(rule) {
rule.tags.forEach(function forTag(tag) {
@ -915,7 +917,7 @@ test.cb("readme", (t) => {
});
test.cb("rules", (t) => {
t.plan(344);
t.plan(352);
fs.readFile("doc/Rules.md", "utf8",
(err, contents) => {
t.falsy(err);
@ -1568,7 +1570,7 @@ test.cb("configBadFilePromise", (t) => {
});
test("allBuiltInRulesHaveValidUrl", (t) => {
t.plan(135);
t.plan(138);
rules.forEach(function forRule(rule) {
t.truthy(rule.information);
t.true(Object.getPrototypeOf(rule.information) === URL.prototype);

View file

@ -1,17 +1,17 @@
# Mixed Emphasis Markers
This paragraph *uses* both _kinds_ of emphasis marker.
This paragraph *uses* both _kinds_ of emphasis marker. {MD049}
This paragraph _uses_ both *kinds* of emphasis marker.
This paragraph _uses_ both *kinds* of emphasis marker. {MD049}
This paragraph *nests both _kinds_ of emphasis* marker.
This paragraph *nests both _kinds_ of emphasis* marker. {MD049}
This paragraph *nests both __kinds__ of emphasis* marker.
This paragraph **nests both __kinds__ of emphasis** marker. {MD050}
This paragraph _nests both *kinds* of emphasis_ marker.
This paragraph _nests both *kinds* of emphasis_ marker. {MD049}
This paragraph _nests both **kinds** of emphasis_ marker. {MD050}
This paragraph _nests both **kinds** of emphasis_ marker. {MD049} {MD050}
This paragraph __nests both **kinds** of emphasis__ marker. {MD050}

View file

@ -40,7 +40,7 @@ Quoted "Vue" and "vue-router"
Emphasized *Vue* and *vue-router*
Underscored _Vue_ and _vue-router_
Underscored _Vue_ and _vue-router_ {MD049}
Call it npm
But not Npm {MD044}

View file

@ -6,7 +6,7 @@ Quoted "Markdownlint" {MD044}
Emphasized *Markdownlint* {MD044}
Emphasized _Markdownlint_ {MD044}
Emphasized _Markdownlint_ {MD044} {MD049}
JavaScript is a language

View file

@ -100,7 +100,7 @@ code
Mixed `code_span`
scenarios
are _also_ okay.
are _also_ okay. {MD049}
Mixed `code*span`
scenarios

View file

@ -1,6 +1,6 @@
# Heading
<!-- markdownlint-disable-file strong-style -->
<!-- markdownlint-disable-file emphasis-style strong-style -->
Line with *Normal emphasis*