| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- module LinkedIn.UIElements.Parser where
- import Prelude
- import Control.Alt ((<|>))
- import Data.Array as A
- import Data.Date (Month(..), Year)
- import Data.Either (hush)
- import Data.Enum (toEnum)
- import Data.Int (fromNumber)
- import Data.List (List(..), (:))
- import Data.List as L
- import Data.List.NonEmpty as NEL
- import Data.List.Types (NonEmptyList)
- import Data.Map (Map)
- import Data.Map as M
- import Data.Maybe (Maybe(..))
- import Data.String as S
- import Data.String.CodePoints (codePointFromChar)
- import Data.Tuple (Tuple(..))
- import LinkedIn.UIElements.Types (Duration(..), JobFlexibility(..), MonthYear(..), MonthYearOrToday(..), TimeSpan(..), UIString(..))
- import Parsing (Parser, ParserT, fail, liftMaybe, runParser)
- import Parsing.Combinators (choice, try)
- import Parsing.String (char, rest, string)
- import Parsing.String.Basic (intDecimal, number, space, takeWhile)
- monthStrToMonth :: Map String Month
- monthStrToMonth = M.fromFoldable (
- Tuple "janv." January
- : Tuple "fév." February
- : Tuple "mars" March
- : Tuple "avr." April
- : Tuple "mai" May
- : Tuple "juin" June
- : Tuple "juil." July
- : Tuple "août" August
- : Tuple "sept." September
- : Tuple "oct." October
- : Tuple "nov." November
- : Tuple "déc." December
- : Nil
- )
- toMonth :: String -> Maybe Month
- toMonth month_ = M.lookup month_ monthStrToMonth
- toYear :: Number -> Maybe Year
- toYear year_ = case fromNumber year_ of
- Just y -> toEnum y
- Nothing -> Nothing
- monthP :: Parser String Month
- monthP = do
- a <- choice $ string <$> (A.fromFoldable $ M.keys monthStrToMonth)
- case toMonth a of
- Just month_ -> pure month_
- Nothing -> fail "Not a month"
- yearP :: Parser String Year
- yearP = do
- a <- number
- case toYear a of
- Just year_ -> pure year_
- Nothing -> fail "Not a year"
- monthYearP :: Parser String MonthYear
- monthYearP = do
- m <- monthP
- _ <- space
- y <- yearP
- pure $ MonthYear m y
- todayP :: Parser String MonthYearOrToday
- todayP = do
- _ <- string("aujourd’hui")
- pure Today
- timeSpanP :: Parser String TimeSpan
- timeSpanP = do
- start <- monthYearP
- _ <- space
- _ <- char('-')
- _ <- space
- end <- MY <$> monthYearP <|> todayP
- pure $ case end of
- Today -> TimeSpanToToday start
- MY my -> TimeSpanBounded start my
- durationP :: Parser String Duration
- durationP = (try yearsMonthP) <|> (try monthsP) <|> yearsP where
- yearsInt = do
- y <- intDecimal
- _ <- space
- _ <- try (string("ans")) <|> string("an")
- pure y
- monthInt = do
- m <- intDecimal
- _ <- space
- _ <- string("mois")
- pure m
- yearsP = do
- y <- yearsInt
- pure $ Years y
- monthsP = do
- y <- monthInt
- pure $ Months y
- yearsMonthP = do
- y <- yearsInt
- _ <- space
- m <- monthInt
- pure $ YearsMonth y m
- jobFlexP :: Parser String JobFlexibility
- jobFlexP = (try hybrid) <|> (try onSite) <|> (try fullRemote) where
- hybrid = do
- _ <- string("Hybride")
- pure JobFlexHybrid
- onSite = do
- _ <- string("Sur site")
- pure JobFlexOnSite
- fullRemote = do
- _ <- string("À distance")
- pure JobFlexFullRemote
- medianDotP ∷ Parser String Char
- medianDotP = char('·') <|> char('•')
- commaP :: Parser String Char
- commaP = char(',')
- stringWithoutCommaP :: Parser String String
- stringWithoutCommaP = takeWhile (\c -> c /= codePointFromChar ',')
- stringWithoutMedianDotP :: Parser String String
- stringWithoutMedianDotP = takeWhile (\c -> c /= codePointFromChar '·' && c /= codePointFromChar '•')
- uiStringP :: Parser String UIString
- uiStringP = (try uiStringdotSeparatedP) <|> uiStringSingleP
- uiStringWithoutMedianDotP ∷ Parser String UIString
- uiStringWithoutMedianDotP = do
- s <- rest
- liftMaybe (\_ -> "nope") $ hush $ runParser s uiStringSingleP
- uiStringdotSeparatedP ∷ Parser String UIString
- uiStringdotSeparatedP = do
- Tuple s1 s2 <- medianDotSeparated
- let
- intoUiElement :: String -> Parser String UIString
- intoUiElement s = liftMaybe (\_ -> "could not convert to ui element") $ hush $ runParser s uiStringSingleP
- s1' <- intoUiElement s1
- s2' <- intoUiElement s2
- pure $ UIStringDotSeparated s1' s2'
- sepBy2 :: forall m s a sep. ParserT s m a -> ParserT s m sep -> ParserT s m (NonEmptyList a)
- sepBy2 p sep = do
- a0 <- p
- a1 <- sep *> p
- as <- L.manyRec $ sep *> p
- pure $ NEL.cons a0 $ NEL.cons' a1 as
- commaSeparated ∷ Parser String (NonEmptyList String)
- commaSeparated = stringWithoutCommaP `sepBy2` commaP
- medianDotSeparated ∷ Parser String (Tuple String String)
- medianDotSeparated = do
- a0 <- stringWithoutMedianDotP
- a1 <- medianDotP *> rest
- pure $ Tuple (S.trim a0) (S.trim a1)
- uiStringSingleP ∷ Parser String UIString
- uiStringSingleP = (try uiStringDurationP) <|> (try uiStringTimeSpanP) <|> (try uiStringJobFlexP) <|> uiStringPlainP
- uiStringDurationP ∷ Parser String UIString
- uiStringDurationP = UIStringDuration <$> durationP
- uiStringTimeSpanP ∷ Parser String UIString
- uiStringTimeSpanP = UIStringTimeSpan <$> timeSpanP
- uiStringJobFlexP ∷ Parser String UIString
- uiStringJobFlexP = UIStringJobFlex <$> jobFlexP
- uiStringPlainP ∷ Parser String UIString
- uiStringPlainP = UIStringPlain <$> rest
|