2020-04-04 01:31:27 +03:00
|
|
|
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)
|
2020-04-04 01:39:50 +03:00
|
|
|
import Review.Fix as Fix
|
2020-04-04 01:31:27 +03:00
|
|
|
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
|
2020-04-04 01:39:50 +03:00
|
|
|
(Just authorAndPackage) :: (Just linkVersion) :: _ :: rest :: [] ->
|
2020-04-04 01:31:27 +03:00
|
|
|
if authorAndPackage == projectName && linkVersion /= version then
|
2020-04-04 01:39:50 +03:00
|
|
|
let
|
|
|
|
range : Range
|
|
|
|
range =
|
|
|
|
{ start =
|
|
|
|
{ row = row + 1
|
|
|
|
, column = match.index + 3
|
|
|
|
}
|
|
|
|
, end =
|
|
|
|
{ row = row + 1
|
|
|
|
, column = match.index + String.length match.match
|
|
|
|
}
|
|
|
|
}
|
|
|
|
in
|
2020-04-04 01:31:27 +03:00
|
|
|
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" ]
|
|
|
|
}
|
2020-04-04 01:39:50 +03:00
|
|
|
range
|
|
|
|
|> Rule.withFixes [ Fix.replaceRangeBy range <| "https://package.elm-lang.org/packages/" ++ projectName ++ "/" ++ version ++ Maybe.withDefault "" rest ]
|
2020-04-04 01:31:27 +03:00
|
|
|
|> Just
|
|
|
|
|
|
|
|
else
|
|
|
|
Nothing
|
|
|
|
|
|
|
|
_ ->
|
|
|
|
Nothing
|