-
Notifications
You must be signed in to change notification settings - Fork 17
feat(#15): markdownlint for check comments
#505
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
Open
Marat-Tim
wants to merge
1
commit into
objectionary:master
Choose a base branch
from
Marat-Tim:15
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
This file contains hidden or 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
92 changes: 92 additions & 0 deletions
92
src/main/java/org/eolang/lints/LtInvalidMarkdownComment.java
This file contains hidden or 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,92 @@ | ||
| /* | ||
| * SPDX-FileCopyrightText: Copyright (c) 2016-2025 Objectionary.com | ||
| * SPDX-License-Identifier: MIT | ||
| */ | ||
| package org.eolang.lints; | ||
|
|
||
| import com.github.lombrozo.xnav.Xnav; | ||
| import com.jcabi.xml.XML; | ||
| import java.io.IOException; | ||
| import java.util.ArrayList; | ||
| import java.util.Collection; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Set; | ||
| import java.util.stream.Collectors; | ||
| import java.util.stream.Stream; | ||
| import org.cactoos.io.ResourceOf; | ||
| import org.cactoos.text.IoCheckedText; | ||
| import org.cactoos.text.TextOf; | ||
| import org.eolang.parser.OnDefault; | ||
|
|
||
| /** | ||
| * Comments should not be violated from the point of view of markdownlint. | ||
| * This lint works for multiple files, as creating a MarkdownLinter takes a very long time | ||
| * and creating it many times is a bad idea. | ||
| * | ||
| * @since 0.0.47 | ||
| */ | ||
| final class LtInvalidMarkdownComment implements Lint<Map<String, XML>> { | ||
| /** | ||
| * Markdownlint rule names to ignore. | ||
| */ | ||
| private static final Set<String> IGNORED = Set.of( | ||
| "MD041", | ||
| "MD047", | ||
| "MD026" | ||
| ); | ||
|
|
||
| @Override | ||
| public String name() { | ||
| return "invalid-markdown-comment"; | ||
| } | ||
|
|
||
| @Override | ||
| public Collection<Defect> defects(final Map<String, XML> pkg) throws IOException { | ||
| final Collection<Defect> defects = new ArrayList<>(0); | ||
| try (MarkdownLinter mdlinter = new MarkdownLinter()) { | ||
| for (final XML xmir : pkg.values()) { | ||
| this.defectsOfXmir(xmir, mdlinter).forEach(defects::add); | ||
| } | ||
| } | ||
| return defects; | ||
| } | ||
|
|
||
| @Override | ||
| public String motive() throws IOException { | ||
| return new IoCheckedText( | ||
| new TextOf( | ||
| new ResourceOf( | ||
| String.format( | ||
| "org/eolang/motives/comments/%s.md", | ||
| this.name() | ||
| ) | ||
| ) | ||
| ) | ||
| ).asString(); | ||
| } | ||
|
|
||
| private Stream<Defect> defectsOfXmir(final XML xmir, final MarkdownLinter mdlinter) { | ||
| final Stream.Builder<Defect> defects = Stream.builder(); | ||
| final List<Xnav> comments = new Xnav(xmir.inner()).path("/object/comments/comment") | ||
| .collect(Collectors.toList()); | ||
| for (final Xnav comment : comments) { | ||
| final String text = comment.text().get().replace("\\n", "\n"); | ||
| final int length = text.split("\n", -1).length; | ||
| final int line = Integer.parseInt(comment.attribute("line").text().orElse("0")); | ||
| mdlinter.defects(text) | ||
| .filter(defect -> !LtInvalidMarkdownComment.IGNORED.contains(defect.rule())) | ||
| .map( | ||
| defect -> new Defect.Default( | ||
| this.name(), | ||
| defect.severity(), | ||
| new OnDefault(xmir).get(), | ||
| line - 1 - length + defect.line(), | ||
| defect.text() | ||
| ) | ||
| ) | ||
| .forEach(defects::add); | ||
| } | ||
| return defects.build(); | ||
| } | ||
| } |
This file contains hidden or 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,103 @@ | ||
| /* | ||
| * SPDX-FileCopyrightText: Copyright (c) 2016-2025 Objectionary.com | ||
| * SPDX-License-Identifier: MIT | ||
| */ | ||
| package org.eolang.lints; | ||
|
|
||
| import java.io.Closeable; | ||
| import java.util.stream.Stream; | ||
| import org.cactoos.io.ResourceOf; | ||
| import org.cactoos.io.UncheckedInput; | ||
| import org.cactoos.text.FormattedText; | ||
| import org.cactoos.text.TextOf; | ||
| import org.cactoos.text.UncheckedText; | ||
| import org.graalvm.polyglot.Context; | ||
| import org.graalvm.polyglot.Value; | ||
|
|
||
| /** | ||
| * Markdownlint interop. It can take a very long time to create. | ||
| * | ||
| * @since 0.0.47 | ||
| */ | ||
| final class MarkdownLinter implements Closeable { | ||
| /** | ||
| * JavaScript code of markdownlint with function, that run markdownlint on single string. | ||
| */ | ||
| private static final String JSCODE = String.format( | ||
| "%s%s", | ||
| "globalThis.URL=class{constructor(input){this.href=input;}};", | ||
| new UncheckedText( | ||
| new TextOf( | ||
| new UncheckedInput( | ||
| new ResourceOf("markdownlint.js") | ||
| ) | ||
| ) | ||
| ).asString() | ||
| ); | ||
|
|
||
| /** | ||
| * JavaScripts context with markdownlint. | ||
| */ | ||
| private final Context context; | ||
|
|
||
| /** | ||
| * Function lint from JavaScript, that accept string and return rules violations. | ||
| */ | ||
| private final Value mdlint; | ||
|
|
||
| @SuppressWarnings("PMD.ConstructorOnlyInitializesOrCallOtherConstructors") | ||
| MarkdownLinter() { | ||
| this.context = Context.newBuilder("js") | ||
| .option("engine.WarnInterpreterOnly", "false") | ||
| .build(); | ||
| this.context.eval("js", MarkdownLinter.JSCODE); | ||
| this.mdlint = this.context.getBindings("js").getMember("lint"); | ||
| } | ||
|
|
||
| public Stream<Defect.Default> defects(final String text) { | ||
| final Stream.Builder<Defect.Default> defects = Stream.builder(); | ||
| final Value errors = this.mdlint.execute(text); | ||
| for (int idx = 0; idx < errors.getArraySize(); idx += 1) { | ||
| final Value error = errors.getArrayElement(idx); | ||
| final String rule = rule(error.getMember("ruleNames")); | ||
| defects.add( | ||
| new Defect.Default( | ||
| rule, | ||
| Severity.WARNING, | ||
| error.getMember("lineNumber").asInt(), | ||
| new UncheckedText( | ||
| new FormattedText( | ||
| "[%s] %s. See %s", | ||
| rule, | ||
| error.getMember("ruleDescription").asString(), | ||
| error.getMember("ruleInformation").asString() | ||
| ) | ||
| ).asString() | ||
| ) | ||
| ); | ||
| } | ||
| return defects.build(); | ||
| } | ||
|
|
||
| @Override | ||
| public void close() { | ||
| this.context.close(); | ||
| } | ||
|
|
||
| /** | ||
| * MD rule. | ||
| * | ||
| * @param names Javascript array of names. | ||
| * @return The first name starting with MD. | ||
| * @throws IllegalStateException If no name starting with MD is found. | ||
| */ | ||
| private static String rule(final Value names) { | ||
| for (int idx = 0; idx < names.getArraySize(); idx += 1) { | ||
| final String name = names.getArrayElement(idx).asString(); | ||
| if (name.startsWith("MD")) { | ||
| return name; | ||
| } | ||
| } | ||
| throw new IllegalStateException("cannot find name of markdown lint starting with MD"); | ||
| } | ||
| } |
This file contains hidden or 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
This file contains hidden or 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,20 @@ | ||
| /* | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Marat-Tim let's add puzzle to integrate eslint into repository |
||
| * SPDX-FileCopyrightText: Copyright (c) 2016-2025 Objectionary.com | ||
| * SPDX-License-Identifier: MIT | ||
| */ | ||
| /** | ||
| * @todo #15:45min Add eslint to repository https://github.com/eslint/eslint. | ||
| * We should integrate eslint into repository to monitor the quality of code written in java script. | ||
| */ | ||
| import { lint as lintSync } from "markdownlint/sync"; | ||
|
|
||
| globalThis.lint = function(text) { | ||
| const options = { | ||
| "strings": { | ||
| "file": text | ||
| } | ||
| }; | ||
|
|
||
| const results = lintSync(options); | ||
| return results["file"]; | ||
| } | ||
This file contains hidden or 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,15 @@ | ||
| { | ||
| "type": "module", | ||
| "name": "markdownlint", | ||
| "version": "1.0.0", | ||
| "main": "markdownlint.js", | ||
| "scripts": { | ||
| "postinstall": "npx webpack" | ||
| }, | ||
| "dependencies": { | ||
| "markdownlint": "^0.37.4" | ||
| }, | ||
| "devDependencies": { | ||
| "webpack-cli": "^6.0.1" | ||
| } | ||
| } |
This file contains hidden or 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,24 @@ | ||
| /* | ||
| * SPDX-FileCopyrightText: Copyright (c) 2016-2025 Objectionary.com | ||
| * SPDX-License-Identifier: MIT | ||
| */ | ||
| import path from 'path'; | ||
| import { fileURLToPath } from 'url'; | ||
|
|
||
| export default { | ||
| entry: './markdownlint.js', | ||
| output: { | ||
| filename: '../classes/markdownlint.js', | ||
| path: path.dirname(fileURLToPath(import.meta.url)), | ||
| }, | ||
| mode: 'production', | ||
| target: ['webworker'], | ||
| resolve: { | ||
| fallback: { | ||
| fs: false, | ||
| path: false, | ||
| os: false, | ||
| assert: false, | ||
| }, | ||
| } | ||
| }; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change installDirectory to avoid polluting project root.
Setting
installDirectoryto.will install Node.js in the project root, which could lead to unwanted files in version control.📝 Committable suggestion
🤖 Prompt for AI Agents