Browse Source

Start work on JobsUnifiedTopCard

jherve 1 năm trước cách đây
mục cha
commit
a117029e2b
4 tập tin đã thay đổi với 85 bổ sung5 xóa
  1. 8 1
      src/Content.purs
  2. 56 0
      src/LinkedIn/JobsUnifiedTopCard.purs
  3. 1 0
      src/LinkedIn/Types.purs
  4. 20 4
      src/LinkedIn/Utils.purs

+ 8 - 1
src/Content.purs

@@ -13,9 +13,10 @@ import Effect.Class.Console (logShow)
 import Effect.Console (log)
 import LinkedIn.ArtDecoCard (parseArtDecoCard)
 import LinkedIn.ArtDecoTab (parseArtDecoTab)
+import LinkedIn.JobsUnifiedTopCard (parseJobsUnifiedTopCardElement)
 import LinkedIn.Profile.Project as PP
-import LinkedIn.Profile.WorkExperience as PWE
 import LinkedIn.Profile.Skill as PS
+import LinkedIn.Profile.WorkExperience as PWE
 import Yoga.Tree (Tree, showTree)
 
 main :: Effect Unit
@@ -53,6 +54,12 @@ main = do
         Right p -> do
           logShow $ PS.fromUI p
 
+  case jobsUnifiedTopCard of
+    Nothing -> log "nothing"
+    Just l -> do
+      parsed <- (\(LinkedInUIElement _ n) -> parseJobsUnifiedTopCardElement n) $ NEL.head l
+      logShow parsed
+
 maybeShowTree ∷ Maybe (NonEmptyList LinkedInUIElement) → Effect String
 maybeShowTree Nothing = pure "nope"
 maybeShowTree (Just nel) = do

+ 56 - 0
src/LinkedIn/JobsUnifiedTopCard.purs

@@ -0,0 +1,56 @@
+module LinkedIn.JobsUnifiedTopCard where
+
+import Prelude
+
+import Data.Either (Either(..), hush)
+import Data.Generic.Rep (class Generic)
+import Data.List.Types (NonEmptyList)
+import Data.Maybe (Maybe(..))
+import Data.Show.Generic (genericShow)
+import LinkedIn (DetachedNode)
+import LinkedIn.Types (Parser)
+import LinkedIn.Utils (detachNonEmptyTextChild, queryAndDetachMany, queryAndDetachOne, queryOneAndParse)
+
+data JobsUnifiedTopCardElement = JobsUnifiedTopCardElement {
+  header :: DetachedNode,
+  primaryDescription :: Maybe TopCardPrimaryDescription
+}
+
+data TopCardPrimaryDescription = TopCardPrimaryDescription {
+  link :: DetachedNode,
+  text :: DetachedNode,
+  neutral :: Maybe (NonEmptyList DetachedNode)
+}
+
+derive instance Generic JobsUnifiedTopCardElement _
+derive instance Eq JobsUnifiedTopCardElement
+instance Show JobsUnifiedTopCardElement where
+  show = genericShow
+
+derive instance Generic TopCardPrimaryDescription _
+derive instance Eq TopCardPrimaryDescription
+instance Show TopCardPrimaryDescription where
+  show = genericShow
+
+parseTopCardPrimaryDescription :: Parser TopCardPrimaryDescription
+parseTopCardPrimaryDescription n = do
+  link <- queryAndDetachOne ":scope > a" n
+  text <- detachNonEmptyTextChild n
+  neutral <- queryAndDetachMany "span.tvm__text--neutral" n
+  
+  pure $ ado
+    l <- link
+    t <- text
+  in TopCardPrimaryDescription {link: l, text: t, neutral: hush neutral}
+
+parseJobsUnifiedTopCardElement :: Parser JobsUnifiedTopCardElement
+parseJobsUnifiedTopCardElement n = do
+  h1 <- queryAndDetachOne "h1.job-details-jobs-unified-top-card__job-title" n
+  primary <- queryOneAndParse 
+    "div.job-details-jobs-unified-top-card__primary-description-container > div" 
+    parseTopCardPrimaryDescription
+    n
+
+  pure $ ado
+    h <- h1
+  in JobsUnifiedTopCardElement {header: h, primaryDescription: hush primary}

+ 1 - 0
src/LinkedIn/Types.purs

@@ -11,6 +11,7 @@ import Web.DOM (Node)
 data ParseError =
   NodeNotFoundError String
   | NodeListNotFoundError String
+  | TextNotFoundError
 
 derive instance Generic ParseError _
 derive instance Eq ParseError

+ 20 - 4
src/LinkedIn/Utils.purs

@@ -2,19 +2,22 @@ module LinkedIn.Utils where
 
 import Prelude
 
-import Data.Either (Either(..))
+import Data.Array as A
+import Data.Either (Either(..), note)
+import Data.List as L
 import Data.List.NonEmpty (NonEmptyList)
 import Data.List.NonEmpty as NEL
 import Data.Maybe (Maybe(..), fromJust)
-import Data.Traversable (sequence)
+import Data.Traversable (sequence, traverse)
 import Effect (Effect)
-import LinkedIn (DetachedNode, toDetached)
+import LinkedIn (DetachedNode(..), toDetached)
 import LinkedIn.Types (ParseError(..), Parser)
 import Partial.Unsafe (unsafePartial)
 import Web.DOM (Node, ParentNode)
 import Web.DOM.Element as E
+import Web.DOM.Node as N
 import Web.DOM.NodeList as NL
-import Web.DOM.ParentNode (QuerySelector(..), querySelector, querySelectorAll)
+import Web.DOM.ParentNode (QuerySelector(..), children, querySelector, querySelectorAll)
 
 toParentNode' :: Node -> ParentNode
 toParentNode' n =
@@ -63,3 +66,16 @@ queryManyAndParse selector parser n = do
     Just nodes -> do
       nodes' <- sequence $ map parser nodes :: Effect (NonEmptyList((Either ParseError a)))
       pure $ sequence nodes'
+
+detachNonEmptyTextChild :: Parser DetachedNode
+detachNonEmptyTextChild n = do
+  children <- N.childNodes n
+  childrenArr <- NL.toArray children
+  detached <- traverse parseDetachedNode childrenArr
+  
+  case A.find nonEmptyTextElement detached of
+    Nothing -> pure $ Left TextNotFoundError
+    Just c -> pure $ c
+  where 
+    nonEmptyTextElement (Right (DetachedText t)) | t /= "" = true
+    nonEmptyTextElement _ = false