mirror of
https://github.com/jfmengels/elm-review.git
synced 2024-09-11 16:16:09 +03:00
Add Documentation.ReadmeLinksPointToCurrentVersion rule
This commit is contained in:
parent
1143afeb31
commit
a932f65fe9
6
elm.json
6
elm.json
@ -18,5 +18,7 @@
|
||||
"elm-explorations/test": "1.2.2 <= v < 2.0.0",
|
||||
"stil4m/elm-syntax": "7.1.0 <= v < 8.0.0"
|
||||
},
|
||||
"test-dependencies": {}
|
||||
}
|
||||
"test-dependencies": {
|
||||
"elm/regex": "1.0.0 <= v < 2.0.0"
|
||||
}
|
||||
}
|
||||
|
114
tests/Documentation/ReadmeLinksPointToCurrentVersion.elm
Normal file
114
tests/Documentation/ReadmeLinksPointToCurrentVersion.elm
Normal file
@ -0,0 +1,114 @@
|
||||
module Documentation.ReadmeLinksPointToCurrentVersion exposing (rule)
|
||||
|
||||
{-| Reports links to this project's package documentation on <https://package.elm-lang.org/>,
|
||||
where the version is set to `latest` or a different version than the current version of the package.
|
||||
|
||||
**NOTE**: Just make sure to run tests between bumping the Elm version and publishing the package,
|
||||
otherwise the link for a given version could link to a previous one.
|
||||
|
||||
-}
|
||||
|
||||
import Elm.Package
|
||||
import Elm.Project
|
||||
import Elm.Syntax.Range exposing (Range)
|
||||
import Elm.Version
|
||||
import Regex exposing (Regex)
|
||||
import Review.Rule as Rule exposing (Error, Rule)
|
||||
|
||||
|
||||
rule : Rule
|
||||
rule =
|
||||
Rule.newProjectRuleSchema "ReadmeLinksPointToCurrentVersion" initialProjectContext
|
||||
|> Rule.withElmJsonProjectVisitor elmJsonVisitor
|
||||
|> Rule.withReadmeProjectVisitor readmeVisitor
|
||||
|> Rule.fromProjectRuleSchema
|
||||
|
||||
|
||||
type alias ProjectContext =
|
||||
Maybe
|
||||
{ projectName : String
|
||||
, version : String
|
||||
}
|
||||
|
||||
|
||||
initialProjectContext : ProjectContext
|
||||
initialProjectContext =
|
||||
Nothing
|
||||
|
||||
|
||||
|
||||
-- elm.json VISITOR
|
||||
|
||||
|
||||
elmJsonVisitor : Maybe { a | project : Elm.Project.Project } -> ProjectContext -> ( List nothing, ProjectContext )
|
||||
elmJsonVisitor maybeProject _ =
|
||||
case maybeProject |> Maybe.map .project of
|
||||
Just (Elm.Project.Package pkg) ->
|
||||
( []
|
||||
, Just
|
||||
{ projectName = Elm.Package.toString pkg.name
|
||||
, version = Elm.Version.toString pkg.version
|
||||
}
|
||||
)
|
||||
|
||||
_ ->
|
||||
( [], Nothing )
|
||||
|
||||
|
||||
|
||||
-- README VISITOR
|
||||
|
||||
|
||||
readmeVisitor : Maybe { readmeKey : Rule.ReadmeKey, content : String } -> ProjectContext -> ( List (Error scope), ProjectContext )
|
||||
readmeVisitor maybeReadme maybeContext =
|
||||
case ( maybeReadme, maybeContext ) of
|
||||
( Just { readmeKey, content }, Just context ) ->
|
||||
( findRangeForSubstring context readmeKey content, maybeContext )
|
||||
|
||||
_ ->
|
||||
( [], maybeContext )
|
||||
|
||||
|
||||
linkRegex : Regex
|
||||
linkRegex =
|
||||
Regex.fromString "]\\(https://package\\.elm-lang\\.org/packages/([\\w-]+/[\\w-]+)/(\\w+(\\.\\w+\\.\\w+)?)(.*)\\)"
|
||||
|> Maybe.withDefault Regex.never
|
||||
|
||||
|
||||
findRangeForSubstring : { projectName : String, version : String } -> Rule.ReadmeKey -> String -> List (Error scope)
|
||||
findRangeForSubstring context readmeKey content =
|
||||
content
|
||||
|> String.lines
|
||||
|> List.indexedMap Tuple.pair
|
||||
|> List.concatMap
|
||||
(\( row, line ) ->
|
||||
Regex.find linkRegex line
|
||||
|> List.filterMap (notAMatch context readmeKey row)
|
||||
)
|
||||
|
||||
|
||||
notAMatch : { projectName : String, version : String } -> Rule.ReadmeKey -> Int -> Regex.Match -> Maybe (Error scope)
|
||||
notAMatch { projectName, version } readmeKey row match =
|
||||
case match.submatches of
|
||||
(Just authorAndPackage) :: (Just linkVersion) :: _ ->
|
||||
if authorAndPackage == projectName && linkVersion /= version then
|
||||
Rule.errorForReadme readmeKey
|
||||
{ message = "Link does not point to the current version of the package"
|
||||
, details = [ "I suggest to run elm-review in fix mode" ]
|
||||
}
|
||||
{ start =
|
||||
{ row = row + 1
|
||||
, column = match.index + 3
|
||||
}
|
||||
, end =
|
||||
{ row = row + 1
|
||||
, column = match.index + String.length match.match
|
||||
}
|
||||
}
|
||||
|> Just
|
||||
|
||||
else
|
||||
Nothing
|
||||
|
||||
_ ->
|
||||
Nothing
|
139
tests/Documentation/ReadmeLinksPointToCurrentVersionTest.elm
Normal file
139
tests/Documentation/ReadmeLinksPointToCurrentVersionTest.elm
Normal file
@ -0,0 +1,139 @@
|
||||
module Documentation.ReadmeLinksPointToCurrentVersionTest exposing (all)
|
||||
|
||||
import Documentation.ReadmeLinksPointToCurrentVersion exposing (rule)
|
||||
import Elm.Project
|
||||
import Json.Decode as Decode
|
||||
import Review.Project as Project exposing (Project)
|
||||
import Review.Test exposing (ReviewResult)
|
||||
import Test exposing (Test, describe, test)
|
||||
|
||||
|
||||
testRule : Project -> ReviewResult
|
||||
testRule project =
|
||||
"""module SomeModule exposing (a)
|
||||
a = 1"""
|
||||
|> Review.Test.runWithProjectData project rule
|
||||
|
||||
|
||||
createElmJson : String -> { path : String, raw : String, project : Elm.Project.Project }
|
||||
createElmJson rawElmJson =
|
||||
case Decode.decodeString Elm.Project.decoder rawElmJson of
|
||||
Ok elmJson ->
|
||||
{ path = "elm.json"
|
||||
, raw = rawElmJson
|
||||
, project = elmJson
|
||||
}
|
||||
|
||||
Err _ ->
|
||||
Debug.todo "Invalid elm.json supplied to test"
|
||||
|
||||
|
||||
packageElmJson : String -> String
|
||||
packageElmJson name =
|
||||
"""
|
||||
{
|
||||
"type": "package",
|
||||
"name": \""""
|
||||
++ name
|
||||
++ """",
|
||||
"summary": "Summary",
|
||||
"license": "BSD-3-Clause",
|
||||
"version": "1.2.3",
|
||||
"exposed-modules": [
|
||||
"Exposed"
|
||||
],
|
||||
"elm-version": "0.19.0 <= v < 0.20.0",
|
||||
"dependencies": {
|
||||
"elm/core": "1.0.0 <= v < 2.0.0"
|
||||
},
|
||||
"test-dependencies": {}
|
||||
}"""
|
||||
|
||||
|
||||
message : String
|
||||
message =
|
||||
"Link does not point to the current version of the package"
|
||||
|
||||
|
||||
details : List String
|
||||
details =
|
||||
[ "I suggest to run elm-review in fix mode" ]
|
||||
|
||||
|
||||
readmeWithLink : String -> String
|
||||
readmeWithLink link =
|
||||
"""
|
||||
# My project
|
||||
|
||||
- [my project's thing](""" ++ link ++ """)
|
||||
Don't report:
|
||||
- [this](https://package.elm-lang.org/packages/author/other-package/latest/Module-Name)
|
||||
- [this](https://package.elm-lang.org/packages/author/other-package/1.2.2/Module-Name)
|
||||
- [this](https://package.elm-lang.org/packages/other-author/package/latest/Module-Name)
|
||||
- [this](https://package.elm-lang.org/packages/other-author/package/1.2.4/Module-Name)
|
||||
"""
|
||||
|
||||
|
||||
all : Test
|
||||
all =
|
||||
describe "ReadmeLinksPointToCurrentVersion"
|
||||
[ test "should not report an error if there is no elm.json file" <|
|
||||
\() ->
|
||||
Project.new
|
||||
|> Project.addReadme { path = "README.md", content = readmeWithLink "https://package.elm-lang.org/packages/author/package/1.2.4/Module-Name" }
|
||||
|> testRule
|
||||
|> Review.Test.expectNoErrors
|
||||
, test "should not report an error if there is no README file" <|
|
||||
\() ->
|
||||
Project.new
|
||||
|> Project.addElmJson (createElmJson <| packageElmJson "author/package")
|
||||
|> testRule
|
||||
|> Review.Test.expectNoErrors
|
||||
, test "should not report an error if all the links point to the current project use the correct version" <|
|
||||
\() ->
|
||||
Project.new
|
||||
|> Project.addElmJson (createElmJson <| packageElmJson "author/package")
|
||||
|> Project.addReadme { path = "README.md", content = readmeWithLink "https://package.elm-lang.org/packages/author/package/1.2.3/Module-Name" }
|
||||
|> testRule
|
||||
|> Review.Test.expectNoErrors
|
||||
, test "should report an error if a link points to a different version" <|
|
||||
\() ->
|
||||
Project.new
|
||||
|> Project.addElmJson (createElmJson <| packageElmJson "author/package")
|
||||
|> Project.addReadme { path = "README.md", content = readmeWithLink "https://package.elm-lang.org/packages/author/package/1.2.4/Module-Name" }
|
||||
|> testRule
|
||||
|> Review.Test.expectErrorsForReadme
|
||||
[ Review.Test.error
|
||||
{ message = message
|
||||
, details = details
|
||||
, under = "https://package.elm-lang.org/packages/author/package/1.2.4/Module-Name"
|
||||
}
|
||||
]
|
||||
, test "should report an error if a link points to latest" <|
|
||||
\() ->
|
||||
Project.new
|
||||
|> Project.addElmJson (createElmJson <| packageElmJson "author/package")
|
||||
|> Project.addReadme { path = "README.md", content = readmeWithLink "https://package.elm-lang.org/packages/author/package/latest/Module-Name" }
|
||||
|> testRule
|
||||
|> Review.Test.expectErrorsForReadme
|
||||
[ Review.Test.error
|
||||
{ message = message
|
||||
, details = details
|
||||
, under = "https://package.elm-lang.org/packages/author/package/latest/Module-Name"
|
||||
}
|
||||
]
|
||||
, test "should report an error even if the author or package name contains a dash or digit" <|
|
||||
\() ->
|
||||
Project.new
|
||||
|> Project.addElmJson (createElmJson <| packageElmJson "au-tho5r/pack-age1")
|
||||
|> Project.addReadme { path = "README.md", content = readmeWithLink "https://package.elm-lang.org/packages/au-tho5r/pack-age1/latest/Module-Name" }
|
||||
|> testRule
|
||||
|> Review.Test.expectErrorsForReadme
|
||||
[ Review.Test.error
|
||||
{ message = message
|
||||
, details = details
|
||||
, under = "https://package.elm-lang.org/packages/au-tho5r/pack-age1/latest/Module-Name"
|
||||
}
|
||||
|> Review.Test.whenFixed (readmeWithLink "https://package.elm-lang.org/packages/au-tho5r/pack-age1/1.2.3/Module-Name")
|
||||
]
|
||||
]
|
Loading…
Reference in New Issue
Block a user