summaryrefslogtreecommitdiff
path: root/Utility/HtmlDetect.hs
blob: 57a56c95fefa2f4d0d6af409364ed201b87bc9a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
{- html detection
 -
 - Copyright 2017 Joey Hess <id@joeyh.name>
 -
 - License: BSD-2-clause
 -}

module Utility.HtmlDetect where

import Text.HTML.TagSoup
import Data.Char

-- | Detect if a string is a html document.
--
-- The document many not be valid, and will still be detected as html,
-- as long as it starts with a "<html>" or "<!DOCTYPE html>" tag.
--
-- Html fragments like "<p>this</p>" are not detected as being html,
-- although some browsers may chose to render them as html.
isHtml :: String -> Bool
isHtml = evaluate . canonicalizeTags . parseTags . shorten
  where
	-- We only care about the beginning of the file,
	-- so although tagsoup parses lazily anyway, truncate it.
	shorten = take 16384
	evaluate (TagOpen "!DOCTYPE" ((t, _):_):_) = map toLower t == "html"
	evaluate (TagOpen "html" _:_) = True
	-- Allow some leading whitespace before the tag.
	evaluate (TagText t:rest)
		| all isSpace t = evaluate rest
		| otherwise = False
	-- It would be pretty weird to have a html comment before the html
	-- tag, but easy to allow for.
	evaluate (TagComment _:rest) = evaluate rest
	evaluate _ = False