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

Feature/markdownlint custom config #24

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
4 changes: 2 additions & 2 deletions packages/certification-service/code/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/certification-service/code/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@inditextech/apicertification",
"version": "1.2.0",
"version": "1.3.0",
"description": "API scoring service",
"author": "InditexTech Open Source Office",
"license": "Apache-2.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ const { WARN_SEVERITY } = require("./severity");
const { configValue } = require("../config/config");
const path = require("path");

const markdownEvaluate = async (filepath, ruleset) => {
const markdownEvaluate = async (filepath, ruleset, customConfig) => {
const defaultConfig = configValue("cerws.markdown.markdown-lint-config");
const options = {
files: [filepath],
config: markdownlint.readConfigSync(path.join(process.cwd(), configValue("cerws.markdown.markdown-lint-config"))),
config: customConfig ? customConfig : markdownlint.readConfigSync(path.join(process.cwd(), defaultConfig)),
customRules: ruleset.all,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const CUSTOM_RULES_NAMES = {
};

class DocumentationLinter {
static async lintDocumentation(validationType, rootFolder, api, documentation) {
static async lintDocumentation(validationType, rootFolder, api, documentation, customConfig) {
if (!validationType || validationType === VALIDATION_TYPE_DOCUMENTATION) {
const apiReadmeFile = {
fullPath: path.join(rootFolder, api["definition-path"], "README.md"),
Expand All @@ -25,19 +25,19 @@ class DocumentationLinter {
customRules: DocumentationRuleset.API.resolvedRuleset,
};

const readmeIssues = await this.validateReadme(apiReadmeFile);
const readmeIssues = await this.validateReadme(apiReadmeFile, customConfig);

documentation.documentationValidation.issues.push(...readmeIssues);
}
}

static async validateReadme(readmeFile) {
static async validateReadme(readmeFile, customConfig) {
const issues = [];
const readmePath = readmeFile.fullPath;

if (fs.existsSync(readmePath)) {
if (this.checkMarkdownContent(readmePath)) {
issues.push(...(await lintFileWithMarkdownLint(readmePath, readmeFile.customRules)));
issues.push(...(await lintFileWithMarkdownLint(readmePath, readmeFile.customRules, customConfig)));
issues.forEach((issue) => (issue.fileName = readmeFile.fileName));
} else {
issues.push({
Expand Down
4 changes: 2 additions & 2 deletions packages/certification-service/code/src/verify/lint.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ const lintFilesWithProtolint = async (files, customFlags) => {
return evaluateProtolint(files, customFlags);
};

const lintFileWithMarkdownLint = async (file, ruleset) => {
const lintFileWithMarkdownLint = async (file, ruleset, customConfig) => {
logger.info(`Linting md file ${file} with ruleset ${ruleset}`);
return Object.values(await markdownEvaluate(file, ruleset))[0];
return Object.values(await markdownEvaluate(file, ruleset, customConfig))[0];
};

const generateRandomFolder = () => {
Expand Down
7 changes: 7 additions & 0 deletions packages/certification-service/code/test/data/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,10 @@ SPDX-License-Identifier: Apache-2.0
-->

# Title
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa.

Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem.

Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo.

Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a,
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// SPDX-FileCopyrightText: 2024 Industria de Diseño Textil S.A. INDITEX
//
// SPDX-License-Identifier: Apache-2.0

const markdownlint = require("markdownlint");
const path = require("path");
const { markdownEvaluate } = require("../../src/evaluate/markdownEvaluate");
const { DocumentationRuleset } = require("../../src/evaluate/documentation/documentationRuleset");
const { configValue } = require("../../src/config/config");

jest.mock("markdownlint");

describe("Tests Markdown Evaluation", () => {
afterEach(() => {
jest.clearAllMocks();
});

test("Should call markdownlint with default config file", async () => {
const config = {
default: true,
extends: null,
MD013: false,
severities: [
{
id: "MD025",
severity: 1,
},
],
};
const result = {
"README.md": [
{
lineNumber: 1,
ruleNames: ["EX_MD050", "custom-mandatory-about"],
ruleDescription: "Mandatory About Section",
ruleInformation: null,
errorDetail: null,
errorContext: "Section 'about' must exist",
errorRange: null,
fixInfo: null,
},
{
lineNumber: 3,
ruleNames: ["MD025", "single-title", "single-h1"],
ruleDescription: "Multiple top-level headings in the same document",
ruleInformation: "https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md025.md",
errorDetail: null,
errorContext: "# Top level heading",
errorRange: null,
fixInfo: null,
},
],
};
jest.spyOn(markdownlint, "readConfigSync").mockReturnValue(config);
jest.spyOn(markdownlint.promises, "markdownlint").mockResolvedValue(result);

await markdownEvaluate("README.md", DocumentationRuleset.API.resolvedRuleset);

expect(markdownlint.readConfigSync).toHaveBeenCalledWith(
path.join(process.cwd(), configValue("cerws.markdown.markdown-lint-config")),
);
expect(markdownlint.promises.markdownlint).toHaveBeenCalledWith({
files: ["README.md"],
config: config,
customRules: DocumentationRuleset.API.resolvedRuleset.all,
});
});

test("Should call markdownlint with custom config file", async () => {
const customConfig = {
default: true,
extends: null,
MD013: false,
MD001: false,
};
const result = {
"README.md": [
{
lineNumber: 1,
ruleNames: ["EX_MD050", "custom-mandatory-about"],
ruleDescription: "Mandatory About Section",
ruleInformation: null,
errorDetail: null,
errorContext: "Section 'about' must exist",
errorRange: null,
fixInfo: null,
},
],
};

jest.spyOn(markdownlint.promises, "markdownlint").mockResolvedValue(result);

await markdownEvaluate("README.md", DocumentationRuleset.API.resolvedRuleset, customConfig);

expect(markdownlint.promises.markdownlint).toHaveBeenCalledWith({
files: ["README.md"],
config: customConfig,
customRules: DocumentationRuleset.API.resolvedRuleset.all,
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// SPDX-FileCopyrightText: 2024 Industria de Diseño Textil S.A. INDITEX
//
// SPDX-License-Identifier: Apache-2.0

const path = require("path");
const { DocumentationLinter } = require("../../src/verify/documentationLinter");
const { VALIDATION_TYPE_DOCUMENTATION } = require("../../src/verify/types");
const { DocumentationRuleset } = require("../../src/evaluate/documentation/documentationRuleset");
const linter = require("../../src/verify/lint");

jest.mock("../../src/verify/lint");

describe("Documentation Linter tests", () => {
afterEach(() => {
jest.clearAllMocks();
});

test("Should lint with default config", async () => {
const documentation = { documentationValidation: { validationType: VALIDATION_TYPE_DOCUMENTATION, issues: [] } };
const customConfig = {
default: true,
extends: null,
MD013: false,
MD001: false,
};

jest.spyOn(linter, "lintFileWithMarkdownLint").mockResolvedValueOnce(issues);

await DocumentationLinter.lintDocumentation(
VALIDATION_TYPE_DOCUMENTATION,
path.join(__dirname, "../data/"),
{ "definition-path": "" },
documentation,
undefined,
);

expect(linter.lintFileWithMarkdownLint).toHaveBeenCalledWith(
path.join(__dirname, "../data/README.md"),
DocumentationRuleset.API.resolvedRuleset,
undefined,
);

expect(documentation.documentationValidation.issues).toEqual(issues);
});

test("Should lint with custom config", async () => {
const documentation = { documentationValidation: { validationType: VALIDATION_TYPE_DOCUMENTATION, issues: [] } };
const customConfig = {
default: true,
extends: null,
MD013: false,
MD001: false,
};

jest.spyOn(linter, "lintFileWithMarkdownLint").mockResolvedValueOnce(issues);

await DocumentationLinter.lintDocumentation(
undefined,
path.join(__dirname, "../data/"),
{ "definition-path": "" },
documentation,
customConfig,
);

expect(linter.lintFileWithMarkdownLint).toHaveBeenCalledWith(
path.join(__dirname, "../data/README.md"),
DocumentationRuleset.API.resolvedRuleset,
customConfig,
);

expect(documentation.documentationValidation.issues).toStrictEqual(issues);
});

const issues = [
{
lineNumber: 1,
ruleNames: ["EX_MD050", "custom-mandatory-about"],
ruleDescription: "Mandatory About Section",
ruleInformation: null,
errorDetail: null,
errorContext: "Section 'about' must exist",
errorRange: null,
fixInfo: null,
severity: 1,
fileName: "README.md",
},
{
lineNumber: 7,
ruleNames: ["MD022", "blanks-around-headings"],
ruleDescription: "Headings should be surrounded by blank lines",
ruleInformation: "https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md022.md",
errorDetail: "Expected: 1; Actual: 0; Below",
errorContext: "# Title",
errorRange: null,
fixInfo: {
lineNumber: 8,
insertText: "\n",
},
severity: 1,
fileName: "README.md",
},
{
lineNumber: 14,
ruleNames: ["MD047", "single-trailing-newline"],
ruleDescription: "Files should end with a single newline character",
ruleInformation: "https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md047.md",
errorDetail: null,
errorContext: null,
errorRange: [267, 1],
fixInfo: {
editColumn: 268,
insertText: "\n",
},
severity: 1,
fileName: "README.md",
},
];
});
83 changes: 83 additions & 0 deletions packages/certification-service/code/test/verify/lint.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// SPDX-FileCopyrightText: 2024 Industria de Diseño Textil S.A. INDITEX
//
// SPDX-License-Identifier: Apache-2.0

const { DocumentationRuleset } = require("../../src/evaluate/documentation/documentationRuleset");
const markdownEvaluate = require("../../src/evaluate/markdownEvaluate");
const { lintFileWithMarkdownLint } = require("../../src/verify/lint");

jest.mock("../../src/evaluate/markdownEvaluate");

describe("Lint Tests", () => {
describe("lintFileWithMarkdownLint", () => {
test("Should lint markdown with default", async () => {
const file = "README.md";
const ruleset = DocumentationRuleset.API.resolvedRuleset;

jest.spyOn(markdownEvaluate, "markdownEvaluate").mockResolvedValueOnce(lintResult);

const result = await lintFileWithMarkdownLint(file, ruleset, undefined);

expect(result).toStrictEqual(lintResult["README.md"]);
expect(markdownEvaluate.markdownEvaluate).toHaveBeenCalledWith(file, ruleset, undefined);
});
test("Should lint markdown with custom config", async () => {
const file = "README.md";
const ruleset = DocumentationRuleset.API.resolvedRuleset;
const customConfig = {
default: true,
extends: null,
MD013: false,
MD001: false,
};

jest.spyOn(markdownEvaluate, "markdownEvaluate").mockResolvedValueOnce(lintResult);

const result = await lintFileWithMarkdownLint(file, ruleset, customConfig);

expect(result).toStrictEqual(lintResult["README.md"]);
expect(markdownEvaluate.markdownEvaluate).toHaveBeenCalledWith(file, ruleset, customConfig);
});
});

const lintResult = {
"README.md": [
{
lineNumber: 1,
ruleNames: ["EX_MD050", "custom-mandatory-about"],
ruleDescription: "Mandatory About Section",
ruleInformation: null,
errorDetail: null,
errorContext: "Section 'about' must exist",
errorRange: null,
fixInfo: null,
},
{
lineNumber: 7,
ruleNames: ["MD022", "blanks-around-headings"],
ruleDescription: "Headings should be surrounded by blank lines",
ruleInformation: "https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md022.md",
errorDetail: "Expected: 1; Actual: 0; Below",
errorContext: "# Title",
errorRange: null,
fixInfo: {
lineNumber: 8,
insertText: "\n",
},
},
{
lineNumber: 14,
ruleNames: ["MD047", "single-trailing-newline"],
ruleDescription: "Files should end with a single newline character",
ruleInformation: "https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md047.md",
errorDetail: null,
errorContext: null,
errorRange: [267, 1],
fixInfo: {
editColumn: 268,
insertText: "\n",
},
},
],
};
});