defmodule NLdoc.Validation do @moduledoc """ NLdoc Validation is a library that provides accessibility validation for NLdoc documents. TODO: proper description """ alias NLdoc.Spec.Validation.Finding alias NLdoc.Validation.State @rules [ NLdoc.Validation.Rules.DefinitionListHasDefinitionTerm, NLdoc.Validation.Rules.DefinitionTermHasDefinitionDetails, NLdoc.Validation.Rules.EmptyDefinitionDetails, NLdoc.Validation.Rules.EmptyDefinitionTerm, NLdoc.Validation.Rules.EmptyHeading, NLdoc.Validation.Rules.EmptyTableHeader, NLdoc.Validation.Rules.HeadingLevelValid, NLdoc.Validation.Rules.HeadingOrder, NLdoc.Validation.Rules.ImageMustHaveAlt, NLdoc.Validation.Rules.LinkName, NLdoc.Validation.Rules.NoUnderline, NLdoc.Validation.Rules.PAsHeading, NLdoc.Validation.Rules.PageHasHeadingOne, NLdoc.Validation.Rules.PageHasMultipleHeadingOne, NLdoc.Validation.Rules.PageStartsWithHeadingOne, NLdoc.Validation.Rules.StyleBoldInHeading, NLdoc.Validation.Rules.StyleItalicInHeading, NLdoc.Validation.Rules.TableNeedsMultipleRows ] # Mapping from resource types to their applicable rules @rules_by_type Enum.reduce(@rules, %{}, fn rule, acc -> Enum.reduce(rule.validates(), acc, fn type, acc -> Map.update(acc, type, [rule], &[rule | &1]) end) end) @spec validate(NLdoc.Spec.object() | [NLdoc.Spec.object()]) :: [Finding.t()] @spec validate(NLdoc.Spec.object() | [NLdoc.Spec.object()], State.t()) :: State.t() def validate(resource), do: resource |> validate(%State{}) |> State.get(:findings) def validate(resources, state = %State{}) when is_list(resources), do: resources |> Enum.reduce(state, fn resource, state -> resource |> validate(state) end) def validate(resource = %{children: children}, state = %State{}), do: children |> validate(resource |> validate_resource(state)) def validate(resource, state = %State{}), do: resource |> validate_resource(state) for {type, rules} <- @rules_by_type do defp validate_resource(resource = %{__struct__: unquote(type)}, state = %State{}), do: unquote(rules) |> Enum.reduce(state, fn rule, state -> rule.validate(resource, state) end) end defp validate_resource(_, state), do: state end